GitLab Assistant

GitLab Viewer Publish and Deploy Project!

当前为 2023-06-14 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         GitLab Assistant
// @namespace    http://tampermonkey.net/
// @version      1.098
// @description  GitLab Viewer Publish and Deploy Project!
// @author       Sean
// @match        http://192.168.0.200*
// @match        http://192.168.0.200/*
// @match        http://192.168.0.200/fe3project/*
// @match        http://192.168.0.200/frontend_pc/project/*
// @match        https://oa.epoint.com.cn/interaction-design-portal/portal/pages/casestemplates/casetemplatesdetail*
// @match        https://oa.epoint.com.cn/interaction-design-portal/portal/pages/generalpagetemplates/generalpagetemplatesdetail*
// @match        http://192.168.201.159:9999/webapp/pages/default/onlinecase.html*
// @match        http://192.168.118.60:9999/webapp/pages/caselib/create.html*
// @icon         http://192.168.0.200/assets/favicon-7901bd695fb93edb07975966062049829afb56cf11511236e61bcf425070e36e.png
// @require      https://cdn.bootcdn.net/ajax/libs/vue/2.7.14/vue.min.js
// @require      https://unpkg.com/element-ui/lib/index.js
// @require      https://cdn.bootcdn.net/ajax/libs/jszip/3.7.1/jszip.min.js
// @grant        GM_getResourceURL
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @resource     ElementCSS https://unpkg.com/element-ui/lib/theme-chalk/index.css
// @grant        GM_xmlhttpRequest
// @license      MIT
// @run-at       document-end
// ==/UserScript==


// 个性化 gitlab 样式,
// 满足项目详情多行显示,
// 项目列表中的链接新窗口打开,
// 搜索框 placeholder 个性化提示
// 增加CodePipeline 入口等
(function() {
    'use strict';

    let regs = [/^http:\/\/192\.168\.0\.200\/fe3project\//,
               /^http:\/\/192\.168\.0\.200\/frontend_pc\/project\//,
               /^http:\/\/192\.168\.0\.200/,
               /^http:\/\/192\.168\.0\.200\//];
    let match = false;

    for(let r = 0, lr = regs.length; r < lr; r++) {
        if(regs[r].test(location.href)) {
            match = true;
            break;
        }
    }

    if(!match) {
        return;
    }

    // 注入样式:改变容器宽度,项目描述多行展示
    let injectStyle = ".group-list-tree .group-row-contents .description p { white-space: normal; } .container-limited.limit-container-width { max-width: 1400px } .limit-container-width .info-well {max-width: none;}";

    injectStyle += ".container-fluid.container-limited.limit-container-width .file-holder.readme-holder.limited-width-container .file-content {max-width: none;}"
    injectStyle += 'button:focus {outline-color: transparent !important;}'
    // 添加注入样式
    let extraStyleElement = document.createElement("style");
    extraStyleElement.innerHTML = injectStyle;
    document.head.appendChild(extraStyleElement);

    const fontUrl = 'https://element.eleme.io/2.11/static/element-icons.535877f.woff';

    // 添加样式规则,将字体应用到指定元素上
    GM_addStyle(`
        @font-face {
            font-family: element-icons;
            src: url(${fontUrl}) format("woff");
        }
    `);

    GM_addStyle(GM_getResourceText('ElementCSS'));

    // 改变列表打开链接方式,改为新窗口打开
    let change = false;
    let tryTimes = 3;

    function changeOpenType() {
        if(!change){
            setTimeout(()=> {
                let links = document.querySelectorAll('.description a');
                if(links.length) {
                    for(let i = 0, l = links.length; i < l; i++) {
                        links[i].target = "_blank";
                        if(i === l - 1) {
                            change = true;
                        }
                    }
                } else {
                    changeOpenType();
                }
            }, 1000);
        }
    }

    function stopLinkProp() {
        setTimeout(()=> {
            const links = document.querySelectorAll('.description a');
            for(let i = 0, l = links.length; i < l; i++) {
                links[i].addEventListener('click', ()=> {
                    event.stopPropagation();
                });
            }
        }, 1000);
    }

    // 等待页面加载完成
    window.addEventListener('load', function() {

        var targetDiv = document.querySelector('section');

        if(targetDiv) {
            // 创建一个 Mutation Observer 实例
            var observer = new MutationObserver(function(mutations) {
                // 在这里处理 div 子元素的变化
                mutations.forEach(function(mutation) {
                    if(mutation.addedNodes && mutation.addedNodes.length) {
                        change = false;
                        changeOpenType();

                        stopLinkProp();
                    }
                });
            });

            // 配置 Mutation Observer
            var config = { childList: true, subtree: true };

            // 开始观察目标 div 元素
            observer.observe(targetDiv, config);
        }

        const placeholder = document.createElement('div');

        // 创建 Vue 实例并挂载到页面
        const vueInstance = new Vue({
            el: placeholder,
            methods: {
                // 进入管理平台 code pipeline
                manage() {
                    window.open('http://192.168.219.170/code-pipeline')
                }
            },
            template: `<div id="my-ext" style="margin-top:4px;">
              <el-tooltip content="进入 Code Pipeline 管理平台" placement="top" effect="light">
                <el-button type="primary" icon="el-icon-attract" size="small" circle @click="manage"></el-button>
              </el-tooltip>
            </div>`
        });

        // 将占位元素追加到 body 元素中
        document.querySelector('.title-container').appendChild(vueInstance.$el);

        // 修改 placehodler
        const listInput = document.getElementById('group-filter-form-field');
        const listInput2 = document.getElementById('project-filter-form-field');

        if(listInput) {
            listInput.setAttribute("placeholder", "按项目名称、日期、开发者搜索,关键字≥3");
            listInput.style.width = '305px';
        }
        if(listInput2) {
            listInput2.setAttribute("placeholder", "按项目名称、日期、开发者搜索,关键字≥3");
            listInput2.style.width = '305px';
        }
    });


})();

// GitLab Viewer Publish and Deploy Project
// 查看项目、部署项目、发布项目功能
(function() {
    'use strict';
    let regs = [/^http:\/\/192\.168\.0\.200\/fe3project\//,
               /^http:\/\/192\.168\.0\.200\/frontend_pc\/project\//];
    let match = false;

    for(let r = 0, lr = regs.length; r < lr; r++) {
        if(regs[r].test(location.href)) {
            match = true;
            break;
        }
    }

    if(!match) {
        return;
    }
    /*
    const fontUrl = 'https://element.eleme.io/2.11/static/element-icons.535877f.woff';

    // 添加样式规则,将字体应用到指定元素上
    GM_addStyle(`
        @font-face {
            font-family: element-icons;
            src: url(${fontUrl}) format("woff");
        }
    `);

    GM_addStyle(GM_getResourceText('ElementCSS'));
    */

    let epointCss = ".epoint-tool {position: fixed; bottom: 0%; right:10px; transform: translateY(-40%);}";
    epointCss += ".el-row { padding: 3px 0;} .el-dialog__body .el-tree{min-height: 420px; max-height: 500px;overflow: auto;}";
    epointCss += ".deploy-body {height: 306px;}"
    epointCss += ".el-loading-spinner {margin-top: -60px;} .el-button--primary:focus {outline: 0 !important;}";
    // 添加注入样式
    let extraStyleElement = document.createElement("style");
    extraStyleElement.innerHTML = epointCss;
    document.head.appendChild(extraStyleElement);

    const MyComponent = {
        template: `<div class="epoint-wrap">
            <div class="epoint-tool">
            <el-row><el-button type="primary" icon="el-icon-search" round @click="viewProject">查看</el-button></el-row>
            <el-row>
                <el-tooltip content="一键部署到170服务器" placement="top" effect="light">
                    <el-button type="primary" icon="el-icon-s-unfold" round @click="doDeploy">部署</el-button>
                </el-tooltip>
            </el-row>
            <el-row>
                <el-tooltip content="一键发布到项目案例库" placement="top" effect="light">
                    <el-button type="primary" icon="el-icon-upload" round @click="publish">发布</el-button>
                </el-tooltip>
            </el-row>
            <el-row>
                <el-tooltip content="进入 Code Pipeline 管理平台进行更多操作" placement="top" effect="light">
                    <el-button type="primary" icon="el-icon-attract" round @click="manage">管理</el-button>
                </el-tooltip>
            </el-row>
            </div>
            <el-dialog
              title="目录结构"
              width="900px"
              :append-to-body="true"
              :visible.sync="dialogVisible"
              :before-close="handleClose">
                <el-tree
                    class="filter-tree"
                    :data="data"
                    :props="defaultProps"
                    node-key="id"
                    default-expand-all
                    @node-click="handleNodeClick"
                    v-loading="loadingTree"
                    element-loading-background="rgba(255, 255, 255, 1)"
                    element-loading-text="拼命加载中......"
                    ref="tree">
                </el-tree>
            </el-dialog>
            <el-dialog
                title="部署"
                width="420px"
                :visible.sync="depDialogVisible">
                    <div class="deploy-body"
                        v-loading="loading"
                        element-loading-text="正在打包部署至 170 服务器,请耐心等待"
                        element-loading-spinner="el-icon-loading">
                    </div>
            </el-dialog>
            <el-dialog title="部署提示" width="640px" :visible.sync="dialogDeployVisible">
                <el-alert
                    title="此操作将把 GitLab 资源打包部署至 170 服务器,已部署过的项目会进行覆盖部署,是否继续?"
                    type="warning" :closable="false" style="margin-bottom: 20px;">
                </el-alert>
                <el-form :model="form" ref="form" :rules="rules">
                    <el-form-item label="框架类型" :label-width="formLabelWidth" prop="frame">
                        <el-select v-model="form.frame" placeholder="请框架类型">
                            <el-option v-for="item in framework" :key="item.value" :label="item.label" :value="item.value"></el-option>
                        </el-select>
                    </el-form-item>
                </el-form>
                <div slot="footer" class="dialog-footer">
                    <el-button @click="dialogDeployVisible = false">取 消</el-button>
                    <el-button type="primary" @click="doDeploy">确 定</el-button>
                </div>
            </el-dialog>
        </div>`,
        data() {
            return {
                dialogVisible: false, // 查看目录结构弹窗
                data: [], // 目录结构树的数据结构
                defaultProps: {
                    children: 'children',
                    label: 'label'
                },
                loadingTree: false,
                depDialogVisible: false, // 部署中弹窗
                loading: false,
                projectLibUrl: 'http://192.168.118.60:9999/webapp/pages/caselib/create.html', // 项目案例库地址
                projectIsDeployed: false, // 项目是否部署过
                projectFtpUrl: '', // ftp路径
                projectEntryUrl: '', // 项目案例库发布表单的入口页面
                supportDeploy: true, // 项目是否支持部署
                dialogDeployVisible: false,
                formLabelWidth: '120px',
                form: {
                    frame: ''
                },
                framework: [
                    {label: '重构模板', value: 1},
                    {label: 'f9x1.0', value: 2},
                    {label: 'f9x2.0', value: 3},
                    {label: 'f950', value: 4},
                    {label: 'f950sp1', value: 5},
                    {label: 'f950sp2', value: 6},
                    {label: 'f950sp3', value: 7},
                    {label: 'f951', value: 18},
                    {label: 'f940', value: 8},
                    {label: 'f941', value: 10},
                    {label: 'f942', value: 9},
                    {label: 'f934', value: 11},
                    {label: 'f933', value: 12},
                    {label: 'f932', value: 13},
                    {label: 'f9211', value: 14},
                    {label: '骨架', value: 15},
                    {label: 'Vue', value: 16},
                    {label: 'React', value: 17}
                ],
                rules: {
                    frame: [
                        { required: true, message: '请选择框架类型', trigger: 'change' }
                    ]
                },
                clickNodeEntry: null
            };
        },
        methods: {
            handleClose(done) {
                done();
                /*
                this.$confirm('确认关闭?')
                    .then(_ => {
                        done();
                    })
                    .catch(_ => {});*/
            },
            handleNodeClick(data) {
                console.log(data);
                if(data.type === 'folder') {
                    return false;
                }
                var self = this;
                var entry = data.entry;
                self.clickNodeEntry = entry;
                if(self.projectFtpUrl) {
                    window.open('http://192.168.219.170' + self.projectFtpUrl + data.entry);
                    self.clickNodeEntry = null;
                } else {
                    if(this.supportDeploy === false) {
                        this.$message({
                            type: 'error',
                            message: '当前项目暂时只支持查看,请耐心等待功能升级。'
                        });
                        self.clickNodeEntry = null;
                        return false;
                    }

                    this.$confirm('资源未部署,部署至 170 服务器后可查看,是否部署?')
                        .then(_ => {

                        this.dialogDeployVisible = true;
                        /*
                        this.depDialogVisible = true;
                        this.loading = true;
                        // 部署
                        this.getDeployInfo({ type: '1' }, (data)=> {
                            this.loading = false;
                            this.depDialogVisible = false;

                            this.data = data.custom.detail;
                            this.projectFtpUrl = data.custom.ftpUrl;

                            this.$alert('部署成功!', '提示', {
                                confirmButtonText: '确定',
                                callback: action => {
                                    window.open('http://192.168.219.170' + self.projectFtpUrl + entry)
                                }
                            });

                        });*/
                    })
                    .catch(_ => {});
                }
            },
            // 部署
            doDeploy () {
                if(!this.isDownLoadPage()) {
                    return;
                }
                if(!this.dialogDeployVisible) {
                    this.dialogDeployVisible = true;
                    return;
                }

                let self = this;

                this.$refs['form'].validate((valid) => {
                    if (valid) {
                        this.dialogDeployVisible = false;
                        this.depDialogVisible = true;
                        this.loading = true;
                        // 部署
                        this.getDeployInfo({ type: '1', frame: this.form.frame }, (data)=> {
                            this.loading = false;
                            this.depDialogVisible = false;

                            if(!data.custom.text){

                                this.data = data.custom.pageTreeData;
                                this.projectFtpUrl = data.custom.projectRootPath;
                                this.supportDeploy = data.custom.supportDeploy;

                                this.setProjectEntry();
                                // 从部署按钮直接过来的
                                if(!this.clickNodeEntry) {
                                    this.$message({
                                        type: 'success',
                                        message: '部署成功!'
                                    });
                                    // 打开查看弹窗
                                    this.viewProject();
                                } else {// 从点击目录结构过来的,可以调整点击的树节点页面
                                    this.$alert('部署成功!', '提示', {
                                        confirmButtonText: '确定',
                                        callback: action => {
                                            window.open('http://192.168.219.170' + self.projectFtpUrl + self.clickNodeEntry);
                                            self.clickNodeEntry = null;
                                        }
                                    });
                                }

                            } else {
                                this.$message({
                                    type: 'error',
                                    message: data.custom.text
                                });
                            }
                        });
                    } else {
                        console.log('error submit!!');
                        return false;
                    }
                });

                /*
                this.$confirm('此操作将把 GitLab 资源打包部署至 170 服务器,已部署过的项目会进行覆盖部署,是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }).then(() => {
                }).catch(() => {
                    this.$message({
                        type: 'info',
                        message: '已取消部署'
                    });
                });*/
            },
            // 发布项目案例库
            publish () {
                this.$confirm('此操作将把项目发布至 <a href="'+ this.projectLibUrl +'" target="_blank">项目案例库</a>,已发布过的项目案例库会有重复项,是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    dangerouslyUseHTMLString: true,
                    type: 'warning'
                }).then(() => {
                    const themes = document.querySelectorAll('.badge-secondary');
                    let keys = [];

                    for(let i = 0, l = themes.length; i < l; i++) {
                        if(themes[0].innerText == '智能设备' && i > 0) {
                            keys.push(themes[i].innerText);
                        } else if (themes[0].innerText !== '智能设备' && i > 1) {
                            keys.push(themes[i].innerText);
                        }
                    }
                    // 存在更多主题的情况
                    const moreKeyEl = document.querySelector('.gl-w-full .text-nowrap');
                    if(moreKeyEl) {
                        const moreKeyElContent = moreKeyEl.getAttribute('data-content');
                        const regex = />([^<]+)</g;
                        const matches = moreKeyElContent.match(regex);
                        const results = matches.filter(function(match) {
                            return match.length > 3;
                        });
                        const moreKeyData = results.map(function(match) {
                            return match.substring(2, match.length - 2);
                        });

                        if(moreKeyData && moreKeyData.length) {
                            keys = keys.concat(moreKeyData);
                        }
                    }

                    // 组织项目案例库所需参数
                    const projectName = document.querySelector('.home-panel-title').innerText;
                    const projectBU = themes[0] ? themes[0].innerText : null;
                    const projectKeys = keys.join(' ');
                    const entryUrl = this.projectEntryUrl;
                    let projectType = themes[1] ? themes[1].innerText : null;

                    if(themes[0]) {
                        if(themes[0].innerText == '智能设备') {
                            projectType = themes[1] ? themes[0].innerText : null;
                        } else {
                            projectType = themes[1] ? themes[1].innerText : null;
                        }
                    }

                    const destUrl = this.projectLibUrl + '?projectName=' + projectName + '&projectBU=' + projectBU + '&projectType=' + projectType + '&projectKeys=' + projectKeys + '&entryUrl=' + entryUrl + '&git=' + window.location.href;

                    this.$message({
                        type: 'success',
                        message: destUrl
                    });

                    window.open(destUrl);

                }).catch(() => {
                    this.$message({
                        type: 'info',
                        message: '已取消发布'
                    });
                });
            },
            // 查看项目
            viewProject () {
                if(!this.isDownLoadPage()) {
                    return;
                }
                this.dialogVisible = true;
                this.loadingTree = true;
                let self = this;

                // 发送ajax请求,查看是否进行过部署
                this.getDeployInfo((data)=> {
                    // 有部署信息,直接赋值,
                    if(data) {
                        self.projectIsDeployed = true;
                        self.data = data.custom.pageTreeData;
                        self.projectFtpUrl = data.custom.projectRootPath;
                        self.supportDeploy = data.custom.supportDeploy;
                        self.loadingTree = false;

                        self.setProjectEntry();

                    } else {
                        // 无部署信息,仅查看文件目录
                        getZipResource((data)=> {
                            self.data = data;
                            self.loadingTree = false;
                        });
                    }
                });

            },
            // 项目部署信息
            getDeployInfo(params, callback) {
                const projectId = document.body.getAttribute('data-project-id');
                const downloadBtn = document.querySelector('.gl-button.btn-sm.btn-confirm');

                const sourceUrl = downloadBtn.getAttribute('href');
                const downloadUrl = window.location.origin + sourceUrl;
                const files = document.body.getAttribute('data-find-file').split('/');
                const name = document.body.getAttribute('data-project') + '-' + files[files.length - 1];
                const author = document.querySelector('.current-user .gl-font-weight-bold').innerText.trim();
                const projectName = document.querySelector('.sidebar-context-title').innerText.trim();
                const deployManOA = document.querySelector('.current-user>a').getAttribute('data-user');
                const projectGitUrl = 'http://192.168.0.200' + document.body.getAttribute('data-find-file').split('/-/')[0];

                if(typeof params == 'function') {
                    callback = params;
                    params = null;
                }

                if(projectId && projectId.length && sourceUrl) {
                    fetch('http://192.168.219.170:3008/api/getDeployInfo', {
                        method: 'POST',
                        // 允许跨域请求
                        mode: 'cors',
                        headers: {
                            'Accept': 'application/json',
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify({//post请求参数
                            params: {
                                "type": (params && params.type !== undefined) ? params.type : '0',// 0 代表查看, 1代表部署
                                "name": name, // 项目路径英文名
                                "deployMan": author, // 部署人姓名
                                "deployManOA": deployManOA, // 部署人账号
                                "projectName": projectName, // 项目名称
                                "downloadUrl": downloadUrl, // 下载地址
                                "projectId": projectId, // 主键,gitlab上的项目id
                                "projectGitUrl": projectGitUrl,
                                "frame": (params && params.frame) ? params.frame : undefined
                            }
                        })
                    })
                    .then(response => response.text())
                    .then((result) => {
                        var data = JSON.parse(result);
                        callback && callback(data);
                    })
                    .catch(error => {
                        this.depDialogVisible = false;
                        this.dialogVisible = false;
                        this.$message({
                            type: 'error',
                            message: '系统故障,请联系管理员。'
                        });
                        console.error(error);
                    });
                } else {
                    this.$message({
                        type: 'error',
                        message: '本页不支持查看和部署,请至仓库页。'
                    });
                    console.error('部署信息请求参数error');
                }
            },
            // 进入管理平台 code pipeline
            manage() {
                window.open('http://192.168.219.170/code-pipeline')
            },
            // 设置入口
            setProjectEntry(){
                const firstNode = findFirstFileNode(this.data);
                if(firstNode) {
                    this.projectEntryUrl = 'http://192.168.219.170' + this.projectFtpUrl + firstNode.entry;
                }else {
                    this.projectEntryUrl = null;
                }
            },
            isDownLoadPage() {
                const downloadBtn = document.querySelector('.gl-button.btn-sm.btn-confirm');
                const sourceUrl = downloadBtn && downloadBtn.getAttribute('href');

                if(downloadBtn && sourceUrl) {
                    return true;
                } else {
                    this.$message({
                        type: 'error',
                        message: '本页面不支持查看和部署,请移至仓库页。'
                    });
                    return false;
                }
            }
        },
        mounted() {
        }
    };

    const placeholder = document.createElement('div');

    // 创建 Vue 实例并挂载到页面
    const vueInstance = new Vue({
        el: placeholder,
        components: {
            MyComponent
        },
        methods: {
        },
        template: `<my-component></my-component>`
    });

    // 等待页面加载完成
    window.addEventListener('load', function() {
        // 将占位元素追加到 body 元素中
        document.body.appendChild(vueInstance.$el);
    });

    // 将文件条目组织成嵌套结构
    function organizeFileEntries(fileEntries) {
        const root = {
            label: document.querySelector('.home-panel-title').innerText || document.getElementById('project_name_edit').value,
            type: 'folder',
            children: []
        };

        // 创建嵌套结构
        fileEntries.forEach(entry => {
            const pathSegments = entry.name.split('/');
            let currentFolder = root;

            // 遍历路径中的每个部分,创建相应的文件夹节点
            for (let i = 0; i < pathSegments.length - 1; i++) {
                const folderName = pathSegments[i];
                let folder = currentFolder.children.find(child => child.label === folderName);

                if(isExcludeFolder(entry.name)) {
                    continue;
                }

                if (!folder) {
                    folder = {
                        label: folderName,
                        type: 'folder',
                        children: []
                    };
                    currentFolder.children.push(folder);
                }

                currentFolder = folder;
            }

            // 创建文件节点并添加到相应的文件夹中
            const fileName = pathSegments[pathSegments.length - 1];

            if(fileName && fileName.length && isIncludeFile(fileName) && !isExcludeFolder(entry.name)) {
                const fileNode = {
                    label: fileName,
                    type: 'file',
                    entry: entry.name
                };
                currentFolder.children.push(fileNode);
            }
        });

        return [root];
    }
    // 是否排除的文件夹
    function isExcludeFolder(entry) {
        if(entry.indexOf('css') > -1 ||
           entry.indexOf('scss') > -1 ||
           entry.indexOf('js') > -1 ||
           entry.indexOf('images') > -1 ||
           entry.indexOf('fui') > -1 ||
           entry.indexOf('lib') > -1 ||
           entry.indexOf('test') > -1 ||
           entry.indexOf('font') > -1 ||
           entry.indexOf('frame/fui') > -1) {
            return true;
        } else {
            return false;
        }
    }
    // 是否包含的文件
    function isIncludeFile(fileName) {
        if(fileName.indexOf('.html') > -1) {
            return true;
        } else {
            return false;
        }
    }

    function getZipResource(callback) {
        const downloadUrl = window.location.origin + document.querySelector('.gl-button.btn-sm.btn-confirm').getAttribute('href');

        fetch(downloadUrl)
            .then(response => response.arrayBuffer())
            .then(data => {
            // 将 ZIP 文件的二进制数据传递给 JSZip 进行解析
            return JSZip.loadAsync(data);
        })
            .then(zip => {
            // 获取 ZIP 文件中的所有条目(文件和目录)
            const zipEntries = Object.values(zip.files);
            const treeData = organizeFileEntries(zipEntries)

            callback && callback(treeData);

        })
            .catch(error => {
            console.error(error);
        });
    }

    // 树结构第一个节点数据
    function findFirstFileNode(tree) {
        // 遍历树的节点
        for (let i = 0; i < tree.length; i++) {
            const node = tree[i];

            // 如果节点的类型为 file,则返回该节点
            if (node.type === 'file') {
                return node;
            }

            // 如果节点有子节点,则递归调用该函数查找子节点中的第一个 file 节点
            if (node.children && node.children.length > 0) {
                const fileNode = findFirstFileNode(node.children);
                if (fileNode) {
                    return fileNode;
                }
            }
        }

        // 如果没有找到 file 节点,则返回 null
        return null;
    }
})();

// 修改项目描述的长度
(function() {
    'use strict';
    let regs = [/^http:\/\/192\.168\.0\.200\/fe3project\//,
               /^http:\/\/192\.168\.0\.200\/frontend_pc\/project\//];
    let match = false;

    for(let r = 0, lr = regs.length; r < lr; r++) {
        if(regs[r].test(location.href)) {
            match = true;
            break;
        }
    }

    if(!match) {
        return;
    }

    let tryTimes = 6;
    let changed = false;

    // 增加项目描述的输入长度
    function modifyTextareaLen() {
        if(tryTimes > 0 && !changed) {
            setTimeout(() => {
                const textarea = document.getElementById('project_description');
                tryTimes--;
                if(textarea) {
                    textarea.setAttribute("maxlength", "1000");
                    changed = true;
                } else {
                    modifyTextareaLen();
                }
            }, 1000);
        }
    }

    window.onload = function() {
        modifyTextareaLen();
    }
})();

// 设计门户增加通往前端仓库的跳板
(function() {
    'use strict';

    let regs = [/^https:\/\/oa\.epoint\.com\.cn\/interaction-design-portal\/portal\/pages\/casestemplates\/casetemplatesdetail/,
               /^https:\/\/oa\.epoint\.com\.cn\/interaction-design-portal\/portal\/pages\/generalpagetemplates\/generalpagetemplatesdetail/];
    let match = false;

    for(let r = 0, lr = regs.length; r < lr; r++) {
        if(regs[r].test(location.href)) {
            match = true;
            break;
        }
    }

    if(!match) {
        return;
    }


    function addStyle() {
        // 注入样式:增加按钮
        let injectStyle = ".content { position: relative; } .front-proto { position: absolute; top: 20px; right: 20px; width: 106px; height: 36px; border-radius: 4px; cursor: pointer; line-height: 36px; background: #25c2c9; color: #fff; text-align: center; font-size: 14px}";


        // 添加注入样式
        let extraStyleElement = document.createElement("style");
        extraStyleElement.innerHTML = injectStyle;
        document.head.appendChild(extraStyleElement);
    }

    function getUrlParameters() {
        var params = {};
        var search = window.location.search.substring(1);
        var urlParams = search.split('&');

        for (var i = 0; i < urlParams.length; i++) {
            var param = urlParams[i].split('=');
            var paramName = decodeURIComponent(param[0]);
            var paramValue = decodeURIComponent(param[1] || '');
            params[paramName] = paramValue;
        }

        return params;
    }

    window.onload = ()=> {
        addStyle();
        const $content = jQuery('.content');

        $content.append('<div class="front-proto">前端原型</div>');

        const $frontBtn = jQuery('.front-proto', $content);

        $frontBtn.on('click', ()=> {
            window.open('http://192.168.0.200/?name=' + getUrlParameters().guid);
        });
    };
})();

// 前端项目案例库增加获取参数的能力
// 前端项目案例库增加部署能力
(function() {
    'use strict';

    let regs = [/^http:\/\/192\.168\.118\.60:9999\/webapp\/pages\/caselib\/create\.html/,
               /^http:\/\/192\.168\.201\.159:9999\/webapp\/pages\/default\/onlinecase.html/];
    let match = false;

    for(let r = 0, lr = regs.length; r < lr; r++) {
        if(regs[r].test(location.href)) {
            match = true;
            break;
        }
    }

    if(!match) {
        return;
    }

    const fontUrl = 'https://element.eleme.io/2.11/static/element-icons.535877f.woff';

    // 添加样式规则,将字体应用到指定元素上
    GM_addStyle(`
        @font-face {
            font-family: element-icons;
            src: url(${fontUrl}) format("woff");
        }
    `);

    GM_addStyle(GM_getResourceText('ElementCSS'));

    const businessType = [
        { Value: '7a20e23c-30b8-47e2-8d8d-f2691c9c63c4', Text: '政务服务' },
        { Value: 'c12150bb-b358-452f-87f0-8a2254df87cb', Text: '政务协同' },
        { Value: '3845804e-de68-421c-9402-7b238cfb5a70', Text: '大数据' },
        { Value: '3c28ee56-f24d-4843-b9a2-93e6b96264f4', Text: '电子交易' },
        { Value: '673b5918-51bc-4f1a-ab73-fca86e54d7d1', Text: '数字建设' },
        { Value: '6d9e7d84-7de3-4e0f-bd4f-ed4722ed25b5', Text: '建筑企业' },
        { Value: 'c22f8d2f-518d-4381-b88c-1da68536ed3a', Text: '公共安全' },
        { Value: 'c5810829-1b21-4b22-85cd-390b1edd9614', Text: '智能设备' },
        { Value: '080c7560-c261-428b-a45d-b86b57b47ffb', Text: '中央研究院' }
    ];

    const projectType = [
        { Value: 'dca44f63-be3f-4e9c-b78f-d786571c22c9', Text: '网站' },
        { Value: 'c7861460-163b-4060-80ec-d60604c50435', Text: '业务系统' },
        { Value: '49accc71-6f7d-43f3-b726-58decf58b6fa', Text: '智能设备' },
        { Value: '90209c65-1a55-4d8c-a836-2e5c6b834ada', Text: '大屏可视化' },
        { Value: 'fb0415fb-65ee-42c1-895a-dca042c2568e', Text: '中屏可视化' },
        { Value: '2b83f9b1-ec78-4819-a400-d7d49ea1ecc5', Text: '其他' }
    ];

    let $businesstype;
    let $projecttype;

    function getUrlParameters() {
        var params = {};
        var search = window.location.search.substring(1);
        var urlParams = search.split('&');

        for (var i = 0; i < urlParams.length; i++) {
            var param = urlParams[i].split('=');
            var paramName = decodeURIComponent(param[0]);
            var paramValue = decodeURIComponent(param[1] || '');
            if(paramName) {
                params[paramName] = paramValue;
            }
        }

        return params;
    }

    function initForm (params) {
        if(typeof params === 'object') {
            document.getElementsByName('Title')[0].value = params.projectName ? params.projectName : '';
            document.getElementsByName('KeyWords')[0].value = params.projectKeys ? params.projectKeys : '';
            document.getElementsByName('Entry')[0].value = params.entryUrl ? params.entryUrl : '';
            document.getElementsByName('SourceCode')[0].value = params.git ? params.git : '';
        }
    }

    let setSuccess = false;
    let setTimes = 5;

    function initSelect(params) {
        if(typeof params !== 'object') {
            return;
        }

        if(setTimes > 0 && !setSuccess) {
            setTimeout(()=> {
                setTimes--;

                businessType.forEach((item)=> {
                    if(params.projectBU) {
                        if(item.Text === params.projectBU.trim()) {
                            $businesstype.val(item.Value);
                        } else if( params.projectBU.trim() == '一网统管' || params.projectBU.trim() == '一网协同' || params.projectBU.trim() == '一网通办' ) {
                            $businesstype.val('7a20e23c-30b8-47e2-8d8d-f2691c9c63c4');
                        }
                        $businesstype.trigger("chosen:updated");
                    }
                });

                projectType.forEach((item)=> {
                    if(params.projectType && item.Text === params.projectType.trim()) {
                        $projecttype.val(item.Value);
                        $projecttype.trigger("chosen:updated");
                    }
                });

                setSuccess = true;

            }, 1000);
        } else {
            initSelect(params);
        }
    }

    function addRelatedDom() {
        const sourceInput = document.getElementsByName('SourceCode')[0];
        const $sourceInput = jQuery(sourceInput);

        $sourceInput.after('<a class="btn" style="cursor: pointer;margin-left:10px;" id="deploy">部署</a><a class="btn hidden" style="cursor: pointer;margin-left:10px" id="view">查看</a>')
    }

    function addStyle() {
        let epointCss = ".el-loading-spinner {margin-top: -50px;} .el-button--primary:focus {outline: 0 !important;}";
        // 添加注入样式
        let extraStyleElement = document.createElement("style");
        extraStyleElement.innerHTML = epointCss;
        document.head.appendChild(extraStyleElement);
    }

    window.onload = ()=> {
        const params = getUrlParameters();

        // 有参数,进行填充表单
        if(params && params.git) {
            $businesstype = jQuery('#businesstype');
            $projecttype = jQuery('#projecttype');

            initForm(params);
            initSelect(params);

            return false;
        }

        // 没有url参数填充,则做部署功能展示
        addRelatedDom();
        addStyle();

        const placeholder = document.createElement('div');

        // 创建 Vue 实例并挂载到页面
        const vueInstance = new Vue({
            el: placeholder,
            data() {
                return {
                    framework: [
                        {label: '重构模板', value: 1},
                        {label: 'f9x1.0', value: 2},
                        {label: 'f9x2.0', value: 3},
                        {label: 'f950', value: 4},
                        {label: 'f950sp1', value: 5},
                        {label: 'f950sp2', value: 6},
                        {label: 'f950sp3', value: 7},
                        {label: 'f951', value: 18},
                        {label: 'f940', value: 8},
                        {label: 'f941', value: 10},
                        {label: 'f942', value: 9},
                        {label: 'f934', value: 11},
                        {label: 'f933', value: 12},
                        {label: 'f932', value: 13},
                        {label: 'f9211', value: 14},
                        {label: '骨架', value: 15},
                        {label: 'Vue', value: 16},
                        {label: 'React', value: 17}
                    ],
                    data: [], // 目录结构树
                    defaultProps: {
                        children: 'children',
                        label: 'label'
                    },
                    loadingTree: false,
                    dialogVisible: false,
                    dialogDeployVisible: false,
                    showDeployPath: false,
                    depDialogVisible: false,
                    loading: false,
                    formLabelWidth: '120px',
                    supportDeploy: false,
                    form: {
                        frame: '',
                        deployPath: ''
                    },
                    rules: {
                        frame: [
                            { required: true, message: '请选择框架类型', trigger: 'change' }
                        ],
                        deployPath: [
                            { required: true, message: '请输入部署到 170/showcase 下的目标路径名称', trigger: 'change' }
                        ]
                    }
                }
            },
            methods: {
                // 部署
                doDeploy() {
                    let self = this;

                    this.$refs['form'].validate((valid) => {
                        if (valid) {
                            this.dialogDeployVisible = false;
                            this.depDialogVisible = true;
                            this.loading = true;
                            // 部署
                            this.getDeployInfo({ type: '1', frame: this.form.frame, deployPath: this.form.deployPath }, (data)=> {
                                this.loading = false;
                                this.depDialogVisible = false;

                                if(!data.custom.text){

                                    this.data = data.custom.pageTreeData;
                                    this.projectFtpUrl = data.custom.projectRootPath;
                                    this.supportDeploy = data.custom.supportDeploy;

                                    this.$message({
                                        type: 'success',
                                        message: '部署成功!'
                                    });
                                    // 打开查看弹窗
                                    this.viewProject();
                                    this.toggleViewButton(true);

                                } else {
                                    this.$message({
                                        type: 'error',
                                        message: data.custom.text
                                    });
                                }
                            });
                        } else {
                            console.log('error submit!!');
                            return false;
                        }
                    });
                },
                // 项目部署
                getDeployInfo(params, callback) {
                    const author = document.querySelector('#account a').innerText.trim().substring(4);
                    const projectName = document.getElementsByName('Title')[0].value.trim();
                    const projectGitUrl = document.getElementsByName('SourceCode')[0].value.trim();

                    if(typeof params == 'function') {
                        callback = params;
                        params = null;
                    }
                    if(author && author.length && projectGitUrl) {
                        fetch('http://192.168.219.170:3008/api/getDeployInfo', {
                            method: 'POST',
                            // 允许跨域请求
                            mode: 'cors',
                            headers: {
                                'Accept': 'application/json',
                                'Content-Type': 'application/json'
                            },
                            body: JSON.stringify({//post请求参数
                                params: {
                                    "type": (params && params.type !== undefined) ? params.type : '0',// 0 代表查看, 1代表部署
                                    "deployMan": author, // 部署人姓名
                                    "projectName": projectName, // 项目名称
                                    "projectGitUrl": projectGitUrl,
                                    "frame": (params && params.frame) ? params.frame : undefined,
                                    "deployPath": (params && params.deployPath) ? params.deployPath : undefined // 部署的目标目录
                                }
                            })
                        })
                            .then(response => response.text())
                            .then((result) => {
                            var data = JSON.parse(result);
                            callback && callback(data);
                        })
                            .catch(error => {
                            this.depDialogVisible = false;
                            this.dialogVisible = false;
                            this.$message({
                                type: 'error',
                                message: '系统故障,请联系管理员。'
                            });
                            console.error(error);
                        });
                    } else {
                        this.$message({
                            type: 'error',
                            message: '本页面不支持查看和部署,请先登录。'
                        });
                        console.error('部署信息请求参数error');
                    }
                },
                // 查看项目
                viewProject () {
                    this.dialogVisible = true;
                    let self = this;

                    if(this.data) {
                        this.loadingTree = false;
                    } else {
                        this.loadingTree = true;
                        // 发送ajax请求,查看是否进行过部署
                        this.getDeployInfo((data)=> {
                            // 有部署信息,直接赋值,
                            if(data) {
                                self.projectIsDeployed = true;
                                self.data = data.custom.pageTreeData;
                                self.projectFtpUrl = data.custom.projectRootPath;
                                self.supportDeploy = data.custom.supportDeploy;
                                self.loadingTree = false;

                                self.toggleViewButton(true);

                            }
                        });
                    }
                },
                handleNodeClick(data) {
                    console.log(data);
                    if(data.type === 'folder') {
                        return false;
                    }
                    var self = this;
                    var entry = data.entry;
                    self.clickNodeEntry = entry;
                    if(self.projectFtpUrl) {
                        window.open('http://192.168.219.170' + self.projectFtpUrl + data.entry);
                        self.clickNodeEntry = null;
                    } else {
                        if(this.supportDeploy === false) {
                            this.$message({
                                type: 'error',
                                message: '当前项目暂时只支持查看,请耐心等待功能升级。'
                            });
                            self.clickNodeEntry = null;
                            return false;
                        }

                        this.$confirm('资源未部署,部署至 170 服务器后可查看,是否部署?')
                            .then(_ => {

                            this.dialogDeployVisible = true;
                            })
                            .catch(_ => {});
                    }
                },
                // svn 需要制定目录名称,showDeployPath
                showDialog(showDeployPath) {
                    this.showDeployPath = showDeployPath;
                    this.dialogDeployVisible = true;
                },
                // 查看按钮显影控制
                toggleViewButton(show) {
                    const $viewBtn = jQuery('#view');

                    if(!$viewBtn.length) {
                        return;
                    }

                    if(show) {
                        $viewBtn.removeClass('hidden');
                    } else {
                        $viewBtn.addClass('hidden');
                    }
                }
            },
            mounted() {
                const $btnDeloy = jQuery('#deploy');
                const $btnView = jQuery('#view');

                // 绑定vue组件外的事件
                $btnDeloy.on('click', function() {
                    // 源码地址和项目名称判断
                    const sourceInput = document.getElementsByName('SourceCode');
                    const projectNameInput = document.getElementsByName('Title');

                    let sourceInputVal = sourceInput[0].value.trim(),
                        projectNameInputVal = projectNameInput[0].value.trim();

                    const gitpattern = /^http:\/\/192\.168/;
                    const svnpattern = /^svn:\/\/192\.168/;
                    const sourcepattern = /^(svn:\/\/192\.168|http:\/\/192\.168)/;

                    if (!sourceInputVal) {
                        vueInstance.$message({
                            type: 'error',
                            message: '请输入源码地址!'
                        });
                        return
                    }

                    if (!sourcepattern.test(sourceInputVal)) {
                        vueInstance.$message({
                            type: 'error',
                            message: '请输入准确的源码 gitlab 或 svn 地址!'
                        });
                        return
                    }

                    if (svnpattern.test(sourceInputVal) && !projectNameInputVal) {
                        vueInstance.$message({
                            type: 'error',
                            message: ' svn 仓库地址部署需要填写项目(案例)名称!'
                        });
                        return
                    }

                    vueInstance.showDialog(svnpattern.test(sourceInputVal));
                });
                // 查看项目
                $btnView.on('click', function() {
                    vueInstance.viewProject();
                });

            },
            template: `<div id="my-form">
            <el-dialog title="部署提示" width="640px" :visible.sync="dialogDeployVisible">
                <el-alert
                    title="此操作将把 GitLab / SVN 资源打包部署至 170 服务器,已部署过的项目会进行覆盖部署,是否继续?"
                    type="warning" :closable="false" style="margin-bottom: 20px;">
                </el-alert>
                <el-form :model="form" ref="form" :rules="rules">
                    <el-form-item label="框架类型" :label-width="formLabelWidth" prop="frame">
                        <el-select v-model="form.frame" placeholder="请框架类型" style="width:380px;">
                            <el-option v-for="item in framework" :key="item.value" :label="item.label" :value="item.value"></el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="部署路径" :label-width="formLabelWidth" prop="deployPath" v-if="showDeployPath">
                        <el-input v-model="form.deployPath" placeholder="请输入部署至服务器 170/showcase 下的目标路径名称" style="width:380px;"></el-input>
                    </el-form-item>
                </el-form>
                <div slot="footer" class="dialog-footer">
                    <el-button @click="dialogDeployVisible = false">取 消</el-button>
                    <el-button type="primary" @click="doDeploy">确 定</el-button>
                </div>
            </el-dialog>
            <el-dialog
                title="部署"
                width="420px"
                :visible.sync="depDialogVisible">
                    <div class="deploy-body"
                        style="height: 306px;"
                        v-loading="loading"
                        element-loading-text="正在打包部署至 170 服务器,请耐心等待"
                        element-loading-spinner="el-icon-loading">
                    </div>
            </el-dialog>
            <el-dialog
              title="目录结构"
              width="900px"
              :append-to-body="true"
              :visible.sync="dialogVisible">
                <el-tree
                    class="filter-tree"
                    :data="data"
                    :props="defaultProps"
                    node-key="id"
                    default-expand-all
                    @node-click="handleNodeClick"
                    v-loading="loadingTree"
                    element-loading-background="rgba(255, 255, 255, 1)"
                    element-loading-text="拼命加载中......"
                    ref="tree">
                </el-tree>
            </el-dialog>
          </div>`
        });

        // 将占位元素追加到 body 元素中
        jQuery('.form-container').after(vueInstance.$el);
    };
})();