- // ==UserScript==
- // @name GitLab Viewer Publish and Deploy Project
- // @namespace http://tampermonkey.net/
- // @version 0.1
- // @description GitLab Viewer Publish and Deploy Project!
- // @author Sean
- // @match http://192.168.0.200/fe3project/*
- // @icon http://192.168.0.200/assets/favicon-7901bd695fb93edb07975966062049829afb56cf11511236e61bcf425070e36e.png
- // @require https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js
- // @require https://unpkg.com/element-ui/lib/index.js
- // @require https://cdn.jsdelivr.net/npm/jszip@3.7.1/dist/jszip.min.js
- // @resource myFontFile https://element.eleme.io/2.11/static/element-icons.535877f.woff
- // @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==
-
- (function() {
- 'use strict';
-
- 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(-50%);}";
- 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 += ".deploy-body .el-loading-spinner {margin-top: -50px;}";
- // 添加注入样式
- 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>
- </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"
- 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>
- </div>`,
- data() {
- return {
- dialogVisible: false, // 查看目录结构弹窗
- data: [], // 目录结构树的数据结构
- defaultProps: {
- children: 'children',
- label: 'label'
- },
- loadingTree: false,
- depDialogVisible: false, // 部署中弹窗
- loading: false,
- projectLibUrl: 'http://192.168.201.159:9999/webapp/pages/default/onlinecase.html', // 项目案例库地址
- projectIsDeployed: false, // 项目是否部署过
- };
- },
- methods: {
- handleClose(done) {
- done();
- /*
- this.$confirm('确认关闭?')
- .then(_ => {
- done();
- })
- .catch(_ => {});*/
- },
- handleNodeClick(data) {
- console.log(data);
- },
- // 部署
- doDeploy () {
- this.$confirm('此操作将把 GitLab 资源打包部署至 170 服务器,已部署过的项目会进行覆盖部署,是否继续?', '提示', {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- }).then(() => {
- this.depDialogVisible = true;
- this.loading = true;
- // 部署
- this.getDeployInfo({ type: '1' }, (data)=> {
- this.loading = false;
- this.depDialogVisible = false;
-
- this.$message({
- type: 'success',
- message: '部署成功!'
- });
-
- // this.data = data;
- // 打开查看弹窗
- });
- }).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 projectName = document.querySelector('.home-panel-title').innerText;
- const projectBU = themes[0] ? themes[0].innerText : null;
- const projectType = themes[1] ? themes[0].innerText : null;
- const projectKeys = keys.join(' ');
- const entryUrl = 'http://test.html';
- this.$message({
- type: 'success',
- message: this.projectLibUrl + '?projectName=' + projectName + '&projectBU=' + projectBU + '&projectType=' + projectType + '&projectKeys=' + projectKeys + '&entryUrl=' + entryUrl
- });
- }).catch(() => {
- this.$message({
- type: 'info',
- message: '已取消发布'
- });
- });
- },
- // 查看项目
- viewProject () {
- this.dialogVisible = true;
- this.loadingTree = true;
- let self = this;
-
- // 发送ajax请求,查看是否进行过部署
- this.getDeployInfo((data)=> {
- // 有部署信息,直接赋值,
- if(true) {
- self.projectIsDeployed = true;
- // self.data = data;
- } else {
- // 无部署信息,仅查看文件目录
- getZipResource((data)=> {
- self.data = data;
- self.loadingTree = false;
- });
- }
- });
-
- },
- // 项目部署信息
- getDeployInfo(params, callback) {
- const projectId = document.body.getAttribute('data-project-id');
- const downloadUrl = window.location.origin + document.querySelector('.gl-button.btn-sm.btn-confirm').getAttribute('href');
-
- if(typeof params == 'function') {
- callback = params;
- params = null;
- }
-
- if(projectId && projectId.length && downloadUrl) {
- GM_xmlhttpRequest({
- method: 'POST',
- url: '',
- data: JSON.stringify({
- projectId: projectId,
- downloadUrl: downloadUrl,
- type: (params && params.type !== undefined) ? params.type : '0'// 0 代表查看, 1代表部署
- }),
- onload: function (res) {
- var data = JSON.parse(res.response).data;
- callback && callback(data);
- }
- });
- } else {
- console.error('部署信息请求参数error');
- }
- }
- },
- 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);
- });
- }
- })();