GitLab Assistant

GitLab Viewer Publish and Deploy Project!

当前为 2023-09-01 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name GitLab Assistant
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.09983
  5. // @description GitLab Viewer Publish and Deploy Project!
  6. // @author Sean
  7. // @match http://192.168.0.200*
  8. // @match http://192.168.0.200/*
  9. // @match http://192.168.0.200/fe3project/*
  10. // @match http://192.168.0.200/frontend_pc/project/*
  11. // @match https://oa.epoint.com.cn/interaction-design-portal/portal/pages/casestemplates/casetemplatesdetail*
  12. // @match https://oa.epoint.com.cn/interaction-design-portal/portal/pages/generalpagetemplates/generalpagetemplatesdetail*
  13. // @match http://192.168.201.159:9999/webapp/pages/default/onlinecase.html*
  14. // @match http://192.168.118.60:9999/webapp/pages/caselib/create.html*
  15. // @match https://oa.epoint.com.cn/epointoa9/frame/fui/pages/themes/aide/aide*
  16. // @match https://oa.epoint.com.cn/interaction-design-portal/portal/pages/casestemplates/casetemplateslist*
  17. // @icon http://192.168.0.200/assets/favicon-7901bd695fb93edb07975966062049829afb56cf11511236e61bcf425070e36e.png
  18. // @require https://cdn.bootcdn.net/ajax/libs/vue/2.7.14/vue.min.js
  19. // @require https://unpkg.com/element-ui/lib/index.js
  20. // @require https://cdn.bootcdn.net/ajax/libs/jszip/3.7.1/jszip.min.js
  21. // @grant GM_getResourceURL
  22. // @grant GM_addStyle
  23. // @grant GM_getResourceText
  24. // @resource ElementCSS https://unpkg.com/element-ui/lib/theme-chalk/index.css
  25. // @grant GM_xmlhttpRequest
  26. // @license MIT
  27. // @run-at document-end
  28. // ==/UserScript==
  29.  
  30.  
  31. // 个性化 gitlab 样式,
  32. // 满足项目详情多行显示,
  33. // 项目列表中的链接新窗口打开,
  34. // 搜索框 placeholder 个性化提示
  35. // 增加CodePipeline 入口等
  36. (function() {
  37. 'use strict';
  38.  
  39. let regs = [/^http:\/\/192\.168\.0\.200\/fe3project\//,
  40. /^http:\/\/192\.168\.0\.200\/frontend_pc\/project\//,
  41. /^http:\/\/192\.168\.0\.200/,
  42. /^http:\/\/192\.168\.0\.200\//];
  43. let match = false;
  44.  
  45. for(let r = 0, lr = regs.length; r < lr; r++) {
  46. if(regs[r].test(location.href)) {
  47. match = true;
  48. break;
  49. }
  50. }
  51.  
  52. if(!match) {
  53. return;
  54. }
  55.  
  56. // 注入样式:改变容器宽度,项目描述多行展示
  57. 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;}";
  58.  
  59. injectStyle += ".container-fluid.container-limited.limit-container-width .file-holder.readme-holder.limited-width-container .file-content {max-width: none;}"
  60. injectStyle += 'button:focus {outline-color: transparent !important;}'
  61. injectStyle += '.has-description .description {word-break: break-all;}'
  62. // 添加注入样式
  63. let extraStyleElement = document.createElement("style");
  64. extraStyleElement.innerHTML = injectStyle;
  65. document.head.appendChild(extraStyleElement);
  66.  
  67. const fontUrl = 'https://element.eleme.io/2.11/static/element-icons.535877f.woff';
  68.  
  69. // 添加样式规则,将字体应用到指定元素上
  70. GM_addStyle(`
  71. @font-face {
  72. font-family: element-icons;
  73. src: url(${fontUrl}) format("woff");
  74. }
  75. `);
  76.  
  77. GM_addStyle(GM_getResourceText('ElementCSS'));
  78.  
  79. // 改变列表打开链接方式,改为新窗口打开
  80. let change = false;
  81. let tryTimes = 3;
  82.  
  83. function changeOpenType() {
  84. if(!change){
  85. setTimeout(()=> {
  86. let links = document.querySelectorAll('.description a');
  87. if(links.length) {
  88. for(let i = 0, l = links.length; i < l; i++) {
  89. links[i].target = "_blank";
  90. if(i === l - 1) {
  91. change = true;
  92. }
  93. }
  94. } else {
  95. changeOpenType();
  96. }
  97. }, 1000);
  98. }
  99. }
  100.  
  101. function stopLinkProp() {
  102. setTimeout(()=> {
  103. const links = document.querySelectorAll('.description a');
  104. for(let i = 0, l = links.length; i < l; i++) {
  105. links[i].addEventListener('click', ()=> {
  106. event.stopPropagation();
  107. });
  108. }
  109. }, 1000);
  110. }
  111.  
  112. // 等待页面加载完成
  113. window.addEventListener('load', function() {
  114.  
  115. var targetDiv = document.querySelector('section');
  116.  
  117. if(targetDiv) {
  118. // 创建一个 Mutation Observer 实例
  119. var observer = new MutationObserver(function(mutations) {
  120. // 在这里处理 div 子元素的变化
  121. mutations.forEach(function(mutation) {
  122. if(mutation.addedNodes && mutation.addedNodes.length) {
  123. change = false;
  124. changeOpenType();
  125.  
  126. stopLinkProp();
  127. }
  128. });
  129. });
  130.  
  131. // 配置 Mutation Observer
  132. var config = { childList: true, subtree: true };
  133.  
  134. // 开始观察目标 div 元素
  135. observer.observe(targetDiv, config);
  136. }
  137.  
  138. const placeholder = document.createElement('div');
  139.  
  140. // 创建 Vue 实例并挂载到页面
  141. const vueInstance = new Vue({
  142. el: placeholder,
  143. methods: {
  144. // 进入管理平台 code pipeline
  145. manage() {
  146. window.open('http://192.168.219.170/code-pipeline')
  147. }
  148. },
  149. template: `<div id="my-ext" style="margin-top:4px;">
  150. <el-tooltip content="进入 Code Pipeline 管理平台" placement="top" effect="light">
  151. <el-button type="primary" icon="el-icon-attract" size="small" circle @click="manage"></el-button>
  152. </el-tooltip>
  153. </div>`
  154. });
  155.  
  156. // 将占位元素追加到 body 元素中
  157. document.querySelector('.title-container').appendChild(vueInstance.$el);
  158.  
  159. // 修改 placehodler
  160. const listInput = document.getElementById('group-filter-form-field');
  161. const listInput2 = document.getElementById('project-filter-form-field');
  162.  
  163. if(listInput) {
  164. listInput.setAttribute("placeholder", "按项目名称、日期、开发者搜索,关键字≥3");
  165. listInput.style.width = '305px';
  166. }
  167. if(listInput2) {
  168. listInput2.setAttribute("placeholder", "按项目名称、日期、开发者搜索,关键字≥3");
  169. listInput2.style.width = '305px';
  170. }
  171. });
  172.  
  173.  
  174. })();
  175.  
  176. (function(){
  177. function convertDateFormat(inputString) {
  178. // 匹配日期格式为yyyy-mm-dd或yyyy-m-dd或yyyy-mm-d或yyyy-m-d的正则表达式
  179. const dateRegex = /\d{4}-\d{1,2}-\d{1,2}/g;
  180.  
  181. // 找到所有匹配的日期格式
  182. const dates = inputString.match(dateRegex);
  183.  
  184. // 如果没有匹配到日期,则直接返回原始字符串
  185. if (!dates || dates.length === 0) {
  186. return inputString;
  187. }
  188.  
  189. // 遍历所有匹配到的日期,进行转换
  190. dates.forEach((date) => {
  191. const [year, month, day] = date.split('-');
  192. const formattedDate = `${parseInt(year, 10)}-${parseInt(month, 10)}-${parseInt(day, 10)}`;
  193. inputString = inputString.replace(date, formattedDate);
  194. });
  195.  
  196. return inputString;
  197. }
  198.  
  199. function getUrlParameters() {
  200. var params = {};
  201. var search = window.location.search.substring(1);
  202. var urlParams = search.split('&');
  203.  
  204. for (var i = 0; i < urlParams.length; i++) {
  205. var param = urlParams[i].split('=');
  206. var paramName = decodeURIComponent(param[0]);
  207. var paramValue = decodeURIComponent(param[1] || '');
  208. if(paramName) {
  209. params[paramName] = paramValue;
  210. }
  211. }
  212.  
  213. return params;
  214. }
  215.  
  216. window.convertDateFormat = convertDateFormat;
  217.  
  218. window.gitlabUtil = {
  219. getUrlParameters: getUrlParameters
  220. }
  221. })();
  222.  
  223. // GitLab Viewer Publish and Deploy Project
  224. // 查看项目、部署项目、发布项目功能
  225. // 添加搜索设计门户资源功能
  226. (function() {
  227. 'use strict';
  228. let regs = [/^http:\/\/192\.168\.0\.200\/fe3project\//,
  229. /^http:\/\/192\.168\.0\.200\/frontend_pc\/project\//];
  230. let match = false;
  231.  
  232. for(let r = 0, lr = regs.length; r < lr; r++) {
  233. if(regs[r].test(location.href)) {
  234. match = true;
  235. break;
  236. }
  237. }
  238.  
  239. if(!match) {
  240. return;
  241. }
  242. /*
  243. const fontUrl = 'https://element.eleme.io/2.11/static/element-icons.535877f.woff';
  244.  
  245. // 添加样式规则,将字体应用到指定元素上
  246. GM_addStyle(`
  247. @font-face {
  248. font-family: element-icons;
  249. src: url(${fontUrl}) format("woff");
  250. }
  251. `);
  252.  
  253. GM_addStyle(GM_getResourceText('ElementCSS'));
  254. */
  255.  
  256. let epointCss = ".epoint-tool {position: fixed; bottom: 0%; right:10px; transform: translateY(-40%);}";
  257. epointCss += ".el-row { padding: 6px 0;} .el-dialog__body .el-tree{min-height: 420px; max-height: 500px;overflow: auto;}";
  258. epointCss += ".view-toolbar {padding-bottom: 10px;}";
  259. epointCss += ".deploy-body {height: 306px;}"
  260. epointCss += ".el-loading-spinner {margin-top: -60px;} .el-button--primary:focus {outline: 0 !important;}";
  261.  
  262. // 添加注入样式
  263. let extraStyleElement = document.createElement("style");
  264. extraStyleElement.innerHTML = epointCss;
  265. document.head.appendChild(extraStyleElement);
  266.  
  267. const MyComponent = {
  268. template: `<div class="epoint-wrap">
  269. <div class="epoint-tool">
  270. <el-row>
  271. <el-tooltip content="查看项目页面和模块结构" placement="left" effect="light">
  272. <el-button type="primary" icon="el-icon-search" round @click="viewProject">查看</el-button>
  273. </el-tooltip>
  274. </el-row>
  275. <el-row>
  276. <el-tooltip content="一键部署到170服务器" placement="left" effect="light">
  277. <el-button type="primary" icon="el-icon-s-unfold" round @click="doDeploy">部署</el-button>
  278. </el-tooltip>
  279. </el-row>
  280. <el-row>
  281. <el-tooltip content="一键发布到项目案例库" placement="left" effect="light">
  282. <el-button type="primary" icon="el-icon-upload" round @click="publish">发布</el-button>
  283. </el-tooltip>
  284. </el-row>
  285. <el-row>
  286. <el-tooltip content="进入 Code Pipeline 管理平台进行更多操作" placement="left" effect="light">
  287. <el-button type="primary" icon="el-icon-attract" round @click="manage">管理</el-button>
  288. </el-tooltip>
  289. </el-row>
  290. </div>
  291. <el-dialog
  292. title="目录结构"
  293. width="900px"
  294. :append-to-body="true"
  295. :visible.sync="dialogVisible"
  296. :before-close="handleClose">
  297. <div class="view-body">
  298. <div class="view-toolbar" v-if="projectFtpUrl"><el-button type="primary" size="small" @click="viewAll">查看全部</el-button></div>
  299. <div class="view-content">
  300. <el-tree
  301. class="filter-tree"
  302. :data="data"
  303. :props="defaultProps"
  304. node-key="id"
  305. default-expand-all
  306. @node-click="handleNodeClick"
  307. v-loading="loadingTree"
  308. element-loading-background="rgba(255, 255, 255, 1)"
  309. element-loading-text="拼命加载中......"
  310. ref="tree">
  311. </el-tree>
  312. </div>
  313. </div>
  314. </el-dialog>
  315. <el-dialog
  316. title="部署"
  317. width="420px"
  318. :visible.sync="depDialogVisible">
  319. <div class="deploy-body"
  320. v-loading="loading"
  321. element-loading-text="正在打包部署至 170 服务器,请耐心等待"
  322. element-loading-spinner="el-icon-loading">
  323. </div>
  324. </el-dialog>
  325. <el-dialog title="部署提示" width="640px" :visible.sync="dialogDeployVisible">
  326. <el-alert
  327. title="此操作将把 GitLab 资源打包部署至 170 服务器,已部署过的项目会进行覆盖部署,是否继续?"
  328. type="warning" :closable="false" style="margin-bottom: 20px;">
  329. </el-alert>
  330. <el-form :model="form" ref="form" :rules="rules">
  331. <el-form-item label="框架类型" :label-width="formLabelWidth" prop="frame">
  332. <el-select v-model="form.frame" placeholder="请框架类型">
  333. <el-option v-for="item in framework" :key="item.value" :label="item.label" :value="item.value"></el-option>
  334. </el-select>
  335. </el-form-item>
  336. </el-form>
  337. <div slot="footer" class="dialog-footer">
  338. <el-button @click="dialogDeployVisible = false">取 消</el-button>
  339. <el-button type="primary" @click="doDeploy">确 定</el-button>
  340. </div>
  341. </el-dialog>
  342. </div>`,
  343. data() {
  344. return {
  345. dialogVisible: false, // 查看目录结构弹窗
  346. data: [], // 目录结构树的数据结构
  347. defaultProps: {
  348. children: 'children',
  349. label: 'label'
  350. },
  351. loadingTree: false,
  352. depDialogVisible: false, // 部署中弹窗
  353. loading: false,
  354. projectLibUrl: 'http://192.168.118.60:9999/webapp/pages/caselib/create.html', // 项目案例库地址
  355. projectIsDeployed: false, // 项目是否部署过
  356. projectFtpUrl: '', // ftp路径
  357. projectEntryUrl: '', // 项目案例库发布表单的入口页面
  358. supportDeploy: true, // 项目是否支持部署
  359. dialogDeployVisible: false,
  360. formLabelWidth: '120px',
  361. form: {
  362. frame: ''
  363. },
  364. framework: [
  365. {label: '重构模板', value: 1},
  366. {label: 'f9x1.0', value: 2},
  367. {label: 'f9x2.0', value: 3},
  368. {label: 'f950', value: 4},
  369. {label: 'f950sp1', value: 5},
  370. {label: 'f950sp2', value: 6},
  371. {label: 'f950sp3', value: 7},
  372. {label: 'f951', value: 18},
  373. {label: 'f940', value: 8},
  374. {label: 'f941', value: 10},
  375. {label: 'f942', value: 9},
  376. {label: 'f934', value: 11},
  377. {label: 'f933', value: 12},
  378. {label: 'f932', value: 13},
  379. {label: 'f9211', value: 14},
  380. {label: '骨架', value: 15},
  381. {label: 'Vue', value: 16},
  382. {label: 'React', value: 17}
  383. ],
  384. rules: {
  385. frame: [
  386. { required: true, message: '请选择框架类型', trigger: 'change' }
  387. ]
  388. },
  389. clickNodeEntry: null
  390. };
  391. },
  392. methods: {
  393. handleClose(done) {
  394. done();
  395. /*
  396. this.$confirm('确认关闭?')
  397. .then(_ => {
  398. done();
  399. })
  400. .catch(_ => {});*/
  401. },
  402. handleNodeClick(data) {
  403. console.log(data);
  404. if(data.type === 'folder') {
  405. return false;
  406. }
  407. var self = this;
  408. var entry = data.entry;
  409. self.clickNodeEntry = entry;
  410. if(self.projectFtpUrl) {
  411. window.open('http://192.168.219.170' + self.projectFtpUrl + data.entry);
  412. self.clickNodeEntry = null;
  413. } else {
  414. if(this.supportDeploy === false) {
  415. this.$message({
  416. type: 'error',
  417. message: '当前项目暂时只支持查看,请耐心等待功能升级。'
  418. });
  419. self.clickNodeEntry = null;
  420. return false;
  421. }
  422.  
  423. this.$confirm('资源未部署,部署至 170 服务器后可查看,是否部署?')
  424. .then(_ => {
  425.  
  426. this.dialogDeployVisible = true;
  427. /*
  428. this.depDialogVisible = true;
  429. this.loading = true;
  430. // 部署
  431. this.getDeployInfo({ type: '1' }, (data)=> {
  432. this.loading = false;
  433. this.depDialogVisible = false;
  434.  
  435. this.data = data.custom.detail;
  436. this.projectFtpUrl = data.custom.ftpUrl;
  437.  
  438. this.$alert('部署成功!', '提示', {
  439. confirmButtonText: '确定',
  440. callback: action => {
  441. window.open('http://192.168.219.170' + self.projectFtpUrl + entry)
  442. }
  443. });
  444.  
  445. });*/
  446. })
  447. .catch(_ => {});
  448. }
  449. },
  450. // 部署
  451. doDeploy () {
  452. if(!this.isDownLoadPage()) {
  453. return;
  454. }
  455. if(!this.dialogDeployVisible) {
  456. this.dialogDeployVisible = true;
  457. return;
  458. }
  459.  
  460. let self = this;
  461.  
  462. this.$refs['form'].validate((valid) => {
  463. if (valid) {
  464. this.dialogDeployVisible = false;
  465. this.depDialogVisible = true;
  466. this.loading = true;
  467. // 部署
  468. this.getDeployInfo({ type: '1', frame: this.form.frame }, (data)=> {
  469. this.loading = false;
  470. this.depDialogVisible = false;
  471.  
  472. if(!data.custom.text){
  473.  
  474. this.data = data.custom.pageTreeData;
  475. this.projectFtpUrl = data.custom.projectRootPath;
  476. this.supportDeploy = data.custom.supportDeploy;
  477.  
  478. this.setProjectEntry();
  479. // 从部署按钮直接过来的
  480. if(!this.clickNodeEntry) {
  481. this.$message({
  482. type: 'success',
  483. message: '部署成功!'
  484. });
  485. // 打开查看弹窗
  486. this.viewProject();
  487. } else {// 从点击目录结构过来的,可以调整点击的树节点页面
  488. this.$alert('部署成功!', '提示', {
  489. confirmButtonText: '确定',
  490. callback: action => {
  491. window.open('http://192.168.219.170' + self.projectFtpUrl + self.clickNodeEntry);
  492. self.clickNodeEntry = null;
  493. }
  494. });
  495. }
  496.  
  497. } else {
  498. this.$message({
  499. type: 'error',
  500. message: data.custom.text
  501. });
  502. }
  503. });
  504. } else {
  505. console.log('error submit!!');
  506. return false;
  507. }
  508. });
  509.  
  510. /*
  511. this.$confirm('此操作将把 GitLab 资源打包部署至 170 服务器,已部署过的项目会进行覆盖部署,是否继续?', '提示', {
  512. confirmButtonText: '确定',
  513. cancelButtonText: '取消',
  514. type: 'warning'
  515. }).then(() => {
  516. }).catch(() => {
  517. this.$message({
  518. type: 'info',
  519. message: '已取消部署'
  520. });
  521. });*/
  522. },
  523. // 发布项目案例库
  524. publish () {
  525. this.$confirm('此操作将把项目发布至 <a href="'+ this.projectLibUrl +'" target="_blank">项目案例库</a>,已发布过的项目案例库会有重复项,是否继续?', '提示', {
  526. confirmButtonText: '确定',
  527. cancelButtonText: '取消',
  528. dangerouslyUseHTMLString: true,
  529. type: 'warning'
  530. }).then(() => {
  531. const themes = document.querySelectorAll('.badge-secondary');
  532. let keys = [];
  533.  
  534. for(let i = 0, l = themes.length; i < l; i++) {
  535. if(themes[0].innerText == '智能设备' && i > 0) {
  536. keys.push(themes[i].innerText);
  537. } else if (themes[0].innerText !== '智能设备' && i > 1) {
  538. keys.push(themes[i].innerText);
  539. }
  540. }
  541. // 存在更多主题的情况
  542. const moreKeyEl = document.querySelector('.gl-w-full .text-nowrap');
  543. if(moreKeyEl) {
  544. const moreKeyElContent = moreKeyEl.getAttribute('data-content');
  545. const regex = />([^<]+)</g;
  546. const matches = moreKeyElContent.match(regex);
  547. const results = matches.filter(function(match) {
  548. return match.length > 3;
  549. });
  550. const moreKeyData = results.map(function(match) {
  551. return match.substring(2, match.length - 2);
  552. });
  553.  
  554. if(moreKeyData && moreKeyData.length) {
  555. keys = keys.concat(moreKeyData);
  556. }
  557. }
  558.  
  559. // 组织项目案例库所需参数
  560. const projectName = document.querySelector('.home-panel-title').innerText;
  561. const projectBU = themes[0] ? themes[0].innerText : null;
  562. const projectKeys = keys.join(' ');
  563. const entryUrl = this.projectEntryUrl;
  564. let projectType = themes[1] ? themes[1].innerText : null;
  565.  
  566. if(themes[0]) {
  567. if(themes[0].innerText == '智能设备') {
  568. projectType = themes[1] ? themes[0].innerText : null;
  569. } else {
  570. projectType = themes[1] ? themes[1].innerText : null;
  571. }
  572. }
  573.  
  574. const destUrl = this.projectLibUrl + '?projectName=' + projectName + '&projectBU=' + projectBU + '&projectType=' + projectType + '&projectKeys=' + projectKeys + '&entryUrl=' + entryUrl + '&git=' + window.location.href;
  575.  
  576. this.$message({
  577. type: 'success',
  578. message: destUrl
  579. });
  580.  
  581. window.open(destUrl);
  582.  
  583. }).catch(() => {
  584. this.$message({
  585. type: 'info',
  586. message: '已取消发布'
  587. });
  588. });
  589. },
  590. // 查看项目
  591. viewProject () {
  592. if(!this.isDownLoadPage()) {
  593. return;
  594. }
  595. this.dialogVisible = true;
  596. this.loadingTree = true;
  597. let self = this;
  598.  
  599. // 发送ajax请求,查看是否进行过部署
  600. this.getDeployInfo((data)=> {
  601. // 有部署信息,直接赋值,
  602. if(data) {
  603. self.projectIsDeployed = true;
  604. self.data = data.custom.pageTreeData;
  605. self.projectFtpUrl = data.custom.projectRootPath;
  606. self.supportDeploy = data.custom.supportDeploy;
  607. self.loadingTree = false;
  608.  
  609. self.setProjectEntry();
  610.  
  611. } else {
  612. // 无部署信息,仅查看文件目录
  613. getZipResource((data)=> {
  614. self.data = data;
  615. self.loadingTree = false;
  616. });
  617. }
  618. });
  619.  
  620. },
  621. // 查看项目的所有页面
  622. viewAll() {
  623. window.open('http://192.168.219.170/code-pipeline/#/project/deploy-preview?rowguid=' + document.body.getAttribute('data-project-id'));
  624. },
  625. // 项目部署信息
  626. getDeployInfo(params, callback) {
  627. const projectId = document.body.getAttribute('data-project-id');
  628. const downloadBtn = document.querySelector('.gl-button.btn-sm.btn-confirm');
  629.  
  630. const sourceUrl = downloadBtn.getAttribute('href');
  631. const downloadUrl = window.location.origin + sourceUrl;
  632. const files = document.body.getAttribute('data-find-file').split('/');
  633. const name = document.body.getAttribute('data-project') + '-' + files[files.length - 1];
  634. const author = document.querySelector('.current-user .gl-font-weight-bold').innerText.trim();
  635. const projectName = document.querySelector('.sidebar-context-title').innerText.trim();
  636. const deployManOA = document.querySelector('.current-user>a').getAttribute('data-user');
  637. const projectGitUrl = 'http://192.168.0.200' + document.body.getAttribute('data-find-file').split('/-/')[0];
  638.  
  639. if(typeof params == 'function') {
  640. callback = params;
  641. params = null;
  642. }
  643.  
  644. if(projectId && projectId.length && sourceUrl) {
  645. fetch('http://192.168.219.170:3008/api/getDeployInfo', {
  646. method: 'POST',
  647. // 允许跨域请求
  648. mode: 'cors',
  649. headers: {
  650. 'Accept': 'application/json',
  651. 'Content-Type': 'application/json'
  652. },
  653. body: JSON.stringify({//post请求参数
  654. params: {
  655. "type": (params && params.type !== undefined) ? params.type : '0',// 0 代表查看, 1代表部署
  656. "name": name, // 项目路径英文名
  657. "deployMan": author, // 部署人姓名
  658. "deployManOA": deployManOA, // 部署人账号
  659. "projectName": projectName, // 项目名称
  660. "downloadUrl": downloadUrl, // 下载地址
  661. "projectId": projectId, // 主键,gitlab上的项目id
  662. "projectGitUrl": projectGitUrl,
  663. "frame": (params && params.frame) ? params.frame : undefined
  664. }
  665. })
  666. })
  667. .then(response => response.text())
  668. .then((result) => {
  669. var data = JSON.parse(result);
  670. callback && callback(data);
  671. })
  672. .catch(error => {
  673. this.depDialogVisible = false;
  674. this.dialogVisible = false;
  675. this.$message({
  676. type: 'error',
  677. message: '系统故障,请联系管理员。'
  678. });
  679. console.error(error);
  680. });
  681. } else {
  682. this.$message({
  683. type: 'error',
  684. message: '本页不支持查看和部署,请至仓库页。'
  685. });
  686. console.error('部署信息请求参数error');
  687. }
  688. },
  689. // 进入管理平台 code pipeline
  690. manage() {
  691. window.open('http://192.168.219.170/code-pipeline')
  692. },
  693. // 设置入口
  694. setProjectEntry(){
  695. const firstNode = findFirstFileNode(this.data);
  696. if(firstNode) {
  697. this.projectEntryUrl = 'http://192.168.219.170' + this.projectFtpUrl + firstNode.entry;
  698. }else {
  699. this.projectEntryUrl = null;
  700. }
  701. },
  702. isDownLoadPage() {
  703. const downloadBtn = document.querySelector('.gl-button.btn-sm.btn-confirm');
  704. const sourceUrl = downloadBtn && downloadBtn.getAttribute('href');
  705.  
  706. if(downloadBtn && sourceUrl) {
  707. return true;
  708. } else {
  709. this.$message({
  710. type: 'error',
  711. message: '本页面不支持查看和部署,请移至仓库页。'
  712. });
  713. return false;
  714. }
  715. }
  716. },
  717. mounted() {
  718. }
  719. };
  720.  
  721. const placeholder = document.createElement('div');
  722.  
  723. // 创建 Vue 实例并挂载到页面
  724. const vueInstance = new Vue({
  725. el: placeholder,
  726. components: {
  727. MyComponent
  728. },
  729. methods: {
  730. },
  731. template: `<my-component></my-component>`
  732. });
  733.  
  734. // 开始在项目仓库页添加搜索设计门户按钮 start
  735. const panel = document.querySelector('.project-home-panel');
  736. let vueInstance2;
  737. const description = document.querySelector('.read-more-container');
  738. const descriptionText = description && description.innerText;
  739. let haveDesignBackupUrl = /casetemplatesdetail\?guid=(?!$)/.test(descriptionText);
  740.  
  741. if(panel && !haveDesignBackupUrl) {
  742. const btnPlaceholder = document.createElement('div');
  743. btnPlaceholder.setAttribute('class', 'epoint-portal-search');
  744. // 创建 Vue 实例并挂载到页面
  745. vueInstance2 = new Vue({
  746. el: btnPlaceholder,
  747. data: function() {
  748. return {
  749. proName: document.querySelector('.home-panel-title').innerText.trim().substring(0, 4)
  750. };
  751. },
  752. methods: {
  753. manage() {
  754. window.open('https://oa.epoint.com.cn/epointoa9/frame/fui/pages/themes/aide/aide?pageId=aide&redirect=https://oa.epoint.com.cn/interaction-design-portal/portal/pages/casestemplates/casetemplateslist?projectname' + this.proName)
  755. }
  756. },
  757. template: `<div style="margin-top:4px;">
  758. <el-tooltip content="新点设计门户中查找此项目" placement="top" effect="light">
  759. <el-button type="primary" icon="el-icon-search" size="small" @click="manage">查找UI备份地址</el-button>
  760. </el-tooltip>
  761. </div>`
  762. });
  763. // 开始在项目仓库页添加搜索设计门户按钮 end
  764. }
  765.  
  766.  
  767. // 等待页面加载完成
  768. window.addEventListener('load', function() {
  769. // 将占位元素追加到 body 元素中
  770. document.body.appendChild(vueInstance.$el);
  771.  
  772. panel && !haveDesignBackupUrl && panel.appendChild(vueInstance2.$el);
  773. });
  774.  
  775. // 将文件条目组织成嵌套结构
  776. function organizeFileEntries(fileEntries) {
  777. const root = {
  778. label: document.querySelector('.home-panel-title').innerText || document.getElementById('project_name_edit').value,
  779. type: 'folder',
  780. children: []
  781. };
  782.  
  783. // 创建嵌套结构
  784. fileEntries.forEach(entry => {
  785. const pathSegments = entry.name.split('/');
  786. let currentFolder = root;
  787.  
  788. // 遍历路径中的每个部分,创建相应的文件夹节点
  789. for (let i = 0; i < pathSegments.length - 1; i++) {
  790. const folderName = pathSegments[i];
  791. let folder = currentFolder.children.find(child => child.label === folderName);
  792.  
  793. if(isExcludeFolder(entry.name)) {
  794. continue;
  795. }
  796.  
  797. if (!folder) {
  798. folder = {
  799. label: folderName,
  800. type: 'folder',
  801. children: []
  802. };
  803. currentFolder.children.push(folder);
  804. }
  805.  
  806. currentFolder = folder;
  807. }
  808.  
  809. // 创建文件节点并添加到相应的文件夹中
  810. const fileName = pathSegments[pathSegments.length - 1];
  811.  
  812. if(fileName && fileName.length && isIncludeFile(fileName) && !isExcludeFolder(entry.name)) {
  813. const fileNode = {
  814. label: fileName,
  815. type: 'file',
  816. entry: entry.name
  817. };
  818. currentFolder.children.push(fileNode);
  819. }
  820. });
  821.  
  822. return [root];
  823. }
  824. // 是否排除的文件夹
  825. function isExcludeFolder(entry) {
  826. if(entry.indexOf('css') > -1 ||
  827. entry.indexOf('scss') > -1 ||
  828. entry.indexOf('js') > -1 ||
  829. entry.indexOf('images') > -1 ||
  830. entry.indexOf('fui') > -1 ||
  831. entry.indexOf('lib') > -1 ||
  832. entry.indexOf('test') > -1 ||
  833. entry.indexOf('font') > -1 ||
  834. entry.indexOf('frame/fui') > -1) {
  835. return true;
  836. } else {
  837. return false;
  838. }
  839. }
  840. // 是否包含的文件
  841. function isIncludeFile(fileName) {
  842. if(fileName.indexOf('.html') > -1) {
  843. return true;
  844. } else {
  845. return false;
  846. }
  847. }
  848.  
  849. function getZipResource(callback) {
  850. const downloadUrl = window.location.origin + document.querySelector('.gl-button.btn-sm.btn-confirm').getAttribute('href');
  851.  
  852. fetch(downloadUrl)
  853. .then(response => response.arrayBuffer())
  854. .then(data => {
  855. // 将 ZIP 文件的二进制数据传递给 JSZip 进行解析
  856. return JSZip.loadAsync(data);
  857. })
  858. .then(zip => {
  859. // 获取 ZIP 文件中的所有条目(文件和目录)
  860. const zipEntries = Object.values(zip.files);
  861. const treeData = organizeFileEntries(zipEntries)
  862.  
  863. callback && callback(treeData);
  864.  
  865. })
  866. .catch(error => {
  867. console.error(error);
  868. });
  869. }
  870.  
  871. // 树结构第一个节点数据
  872. function findFirstFileNode(tree) {
  873. // 遍历树的节点
  874. for (let i = 0; i < tree.length; i++) {
  875. const node = tree[i];
  876.  
  877. // 如果节点的类型为 file,则返回该节点
  878. if (node.type === 'file') {
  879. return node;
  880. }
  881.  
  882. // 如果节点有子节点,则递归调用该函数查找子节点中的第一个 file 节点
  883. if (node.children && node.children.length > 0) {
  884. const fileNode = findFirstFileNode(node.children);
  885. if (fileNode) {
  886. return fileNode;
  887. }
  888. }
  889. }
  890.  
  891. // 如果没有找到 file 节点,则返回 null
  892. return null;
  893. }
  894. })();
  895.  
  896. // 修改项目描述的长度
  897. (function() {
  898. 'use strict';
  899. let regs = [/^http:\/\/192\.168\.0\.200\/fe3project\//,
  900. /^http:\/\/192\.168\.0\.200\/frontend_pc\/project\//];
  901. let match = false;
  902.  
  903. for(let r = 0, lr = regs.length; r < lr; r++) {
  904. if(regs[r].test(location.href)) {
  905. match = true;
  906. break;
  907. }
  908. }
  909.  
  910. if(!match) {
  911. return;
  912. }
  913.  
  914. let tryTimes = 6;
  915. let changed = false;
  916.  
  917. // 增加项目描述的输入长度
  918. function modifyTextareaLen() {
  919. if(tryTimes > 0 && !changed) {
  920. setTimeout(() => {
  921. const textarea = document.getElementById('project_description');
  922. tryTimes--;
  923. if(textarea) {
  924. textarea.setAttribute("maxlength", "1000");
  925.  
  926. jQuery(textarea).blur(function(event) {
  927. this.value = this.value.replace(/,/g, ',').replace(/&isfwqfb=1/g, '');
  928. this.value = convertDateFormat(this.value);
  929. jQuery(this).trigger('change');
  930. });
  931. changed = true;
  932. } else {
  933. modifyTextareaLen();
  934. }
  935. }, 1000);
  936. }
  937. }
  938.  
  939. window.onload = function() {
  940. modifyTextareaLen();
  941. }
  942. })();
  943.  
  944. // 设计门户增加通往前端仓库的跳板
  945. (function() {
  946. 'use strict';
  947.  
  948. let regs = [/^https:\/\/oa\.epoint\.com\.cn\/interaction-design-portal\/portal\/pages\/casestemplates\/casetemplatesdetail/,
  949. /^https:\/\/oa\.epoint\.com\.cn\/interaction-design-portal\/portal\/pages\/generalpagetemplates\/generalpagetemplatesdetail/];
  950. let match = false;
  951.  
  952. for(let r = 0, lr = regs.length; r < lr; r++) {
  953. if(regs[r].test(location.href)) {
  954. match = true;
  955. break;
  956. }
  957. }
  958.  
  959. if(!match) {
  960. return;
  961. }
  962.  
  963.  
  964. function addStyle() {
  965. // 注入样式:增加按钮
  966. 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}";
  967.  
  968.  
  969. // 添加注入样式
  970. let extraStyleElement = document.createElement("style");
  971. extraStyleElement.innerHTML = injectStyle;
  972. document.head.appendChild(extraStyleElement);
  973. }
  974.  
  975. function getUrlParameters() {
  976. var params = {};
  977. var search = window.location.search.substring(1);
  978. var urlParams = search.split('&');
  979.  
  980. for (var i = 0; i < urlParams.length; i++) {
  981. var param = urlParams[i].split('=');
  982. var paramName = decodeURIComponent(param[0]);
  983. var paramValue = decodeURIComponent(param[1] || '');
  984. params[paramName] = paramValue;
  985. }
  986.  
  987. return params;
  988. }
  989.  
  990. window.onload = ()=> {
  991. addStyle();
  992. const $content = jQuery('.content');
  993.  
  994. $content.append('<div class="front-proto">前端原型</div>');
  995.  
  996. const $frontBtn = jQuery('.front-proto', $content);
  997.  
  998. $frontBtn.on('click', ()=> {
  999. window.open('http://192.168.0.200/?name=' + getUrlParameters().guid);
  1000. });
  1001. };
  1002. })();
  1003.  
  1004. // 前端项目案例库增加获取参数的能力
  1005. // 前端项目案例库增加部署能力
  1006. (function() {
  1007. 'use strict';
  1008.  
  1009. let regs = [/^http:\/\/192\.168\.118\.60:9999\/webapp\/pages\/caselib\/create\.html/,
  1010. /^http:\/\/192\.168\.201\.159:9999\/webapp\/pages\/default\/onlinecase.html/];
  1011. let match = false;
  1012.  
  1013. for(let r = 0, lr = regs.length; r < lr; r++) {
  1014. if(regs[r].test(location.href)) {
  1015. match = true;
  1016. break;
  1017. }
  1018. }
  1019.  
  1020. if(!match) {
  1021. return;
  1022. }
  1023.  
  1024. const fontUrl = 'https://element.eleme.io/2.11/static/element-icons.535877f.woff';
  1025.  
  1026. // 添加样式规则,将字体应用到指定元素上
  1027. GM_addStyle(`
  1028. @font-face {
  1029. font-family: element-icons;
  1030. src: url(${fontUrl}) format("woff");
  1031. }
  1032. `);
  1033.  
  1034. GM_addStyle(GM_getResourceText('ElementCSS'));
  1035.  
  1036. const businessType = [
  1037. { Value: '7a20e23c-30b8-47e2-8d8d-f2691c9c63c4', Text: '政务服务' },
  1038. { Value: 'c12150bb-b358-452f-87f0-8a2254df87cb', Text: '政务协同' },
  1039. { Value: '3845804e-de68-421c-9402-7b238cfb5a70', Text: '大数据' },
  1040. { Value: '3c28ee56-f24d-4843-b9a2-93e6b96264f4', Text: '电子交易' },
  1041. { Value: '673b5918-51bc-4f1a-ab73-fca86e54d7d1', Text: '数字建设' },
  1042. { Value: '6d9e7d84-7de3-4e0f-bd4f-ed4722ed25b5', Text: '建筑企业' },
  1043. { Value: 'c22f8d2f-518d-4381-b88c-1da68536ed3a', Text: '公共安全' },
  1044. { Value: 'c5810829-1b21-4b22-85cd-390b1edd9614', Text: '智能设备' },
  1045. { Value: '080c7560-c261-428b-a45d-b86b57b47ffb', Text: '中央研究院' }
  1046. ];
  1047.  
  1048. const projectType = [
  1049. { Value: 'dca44f63-be3f-4e9c-b78f-d786571c22c9', Text: '网站' },
  1050. { Value: 'c7861460-163b-4060-80ec-d60604c50435', Text: '业务系统' },
  1051. { Value: '49accc71-6f7d-43f3-b726-58decf58b6fa', Text: '智能设备' },
  1052. { Value: '90209c65-1a55-4d8c-a836-2e5c6b834ada', Text: '大屏可视化' },
  1053. { Value: 'fb0415fb-65ee-42c1-895a-dca042c2568e', Text: '中屏可视化' },
  1054. { Value: '2b83f9b1-ec78-4819-a400-d7d49ea1ecc5', Text: '其他' }
  1055. ];
  1056.  
  1057. let $businesstype;
  1058. let $projecttype;
  1059.  
  1060. function getUrlParameters() {
  1061. var params = {};
  1062. var search = window.location.search.substring(1);
  1063. var urlParams = search.split('&');
  1064.  
  1065. for (var i = 0; i < urlParams.length; i++) {
  1066. var param = urlParams[i].split('=');
  1067. var paramName = decodeURIComponent(param[0]);
  1068. var paramValue = decodeURIComponent(param[1] || '');
  1069. if(paramName) {
  1070. params[paramName] = paramValue;
  1071. }
  1072. }
  1073.  
  1074. return params;
  1075. }
  1076.  
  1077. function initForm (params) {
  1078. if(typeof params === 'object') {
  1079. document.getElementsByName('Title')[0].value = params.projectName ? params.projectName : '';
  1080. document.getElementsByName('KeyWords')[0].value = params.projectKeys ? params.projectKeys : '';
  1081. document.getElementsByName('Entry')[0].value = params.entryUrl ? params.entryUrl : '';
  1082. document.getElementsByName('SourceCode')[0].value = params.git ? params.git : '';
  1083. }
  1084. }
  1085.  
  1086. let setSuccess = false;
  1087. let setTimes = 5;
  1088.  
  1089. function initSelect(params) {
  1090. if(typeof params !== 'object') {
  1091. return;
  1092. }
  1093.  
  1094. if(setTimes > 0 && !setSuccess) {
  1095. setTimeout(()=> {
  1096. setTimes--;
  1097.  
  1098. businessType.forEach((item)=> {
  1099. if(params.projectBU) {
  1100. if(item.Text === params.projectBU.trim()) {
  1101. $businesstype.val(item.Value);
  1102. } else if( params.projectBU.trim() == '一网统管' || params.projectBU.trim() == '一网协同' || params.projectBU.trim() == '一网通办' ) {
  1103. $businesstype.val('7a20e23c-30b8-47e2-8d8d-f2691c9c63c4');
  1104. }
  1105. $businesstype.trigger("chosen:updated");
  1106. }
  1107. });
  1108.  
  1109. projectType.forEach((item)=> {
  1110. if(params.projectType && item.Text === params.projectType.trim()) {
  1111. $projecttype.val(item.Value);
  1112. $projecttype.trigger("chosen:updated");
  1113. }
  1114. });
  1115.  
  1116. setSuccess = true;
  1117.  
  1118. }, 1000);
  1119. } else {
  1120. initSelect(params);
  1121. }
  1122. }
  1123.  
  1124. function addRelatedDom() {
  1125. const sourceInput = document.getElementsByName('SourceCode')[0];
  1126. const $sourceInput = jQuery(sourceInput);
  1127.  
  1128. $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>')
  1129. }
  1130.  
  1131. function addStyle() {
  1132. let epointCss = ".el-loading-spinner {margin-top: -50px;} .el-button--primary:focus {outline: 0 !important;}";
  1133. // 添加注入样式
  1134. let extraStyleElement = document.createElement("style");
  1135. extraStyleElement.innerHTML = epointCss;
  1136. document.head.appendChild(extraStyleElement);
  1137. }
  1138.  
  1139. window.onload = ()=> {
  1140. const params = getUrlParameters();
  1141.  
  1142. // 有参数,进行填充表单
  1143. if(params && params.git) {
  1144. $businesstype = jQuery('#businesstype');
  1145. $projecttype = jQuery('#projecttype');
  1146.  
  1147. initForm(params);
  1148. initSelect(params);
  1149.  
  1150. return false;
  1151. }
  1152.  
  1153. // 没有url参数填充,则做部署功能展示
  1154. addRelatedDom();
  1155. addStyle();
  1156.  
  1157. const placeholder = document.createElement('div');
  1158.  
  1159. // 创建 Vue 实例并挂载到页面
  1160. const vueInstance = new Vue({
  1161. el: placeholder,
  1162. data() {
  1163. return {
  1164. framework: [
  1165. {label: '重构模板', value: 1},
  1166. {label: 'f9x1.0', value: 2},
  1167. {label: 'f9x2.0', value: 3},
  1168. {label: 'f950', value: 4},
  1169. {label: 'f950sp1', value: 5},
  1170. {label: 'f950sp2', value: 6},
  1171. {label: 'f950sp3', value: 7},
  1172. {label: 'f951', value: 18},
  1173. {label: 'f940', value: 8},
  1174. {label: 'f941', value: 10},
  1175. {label: 'f942', value: 9},
  1176. {label: 'f934', value: 11},
  1177. {label: 'f933', value: 12},
  1178. {label: 'f932', value: 13},
  1179. {label: 'f9211', value: 14},
  1180. {label: '骨架', value: 15},
  1181. {label: 'Vue', value: 16},
  1182. {label: 'React', value: 17}
  1183. ],
  1184. data: [], // 目录结构树
  1185. defaultProps: {
  1186. children: 'children',
  1187. label: 'label'
  1188. },
  1189. loadingTree: false,
  1190. dialogVisible: false,
  1191. dialogDeployVisible: false,
  1192. showDeployPath: false,
  1193. depDialogVisible: false,
  1194. loading: false,
  1195. formLabelWidth: '120px',
  1196. supportDeploy: false,
  1197. form: {
  1198. frame: '',
  1199. deployPath: ''
  1200. },
  1201. rules: {
  1202. frame: [
  1203. { required: true, message: '请选择框架类型', trigger: 'change' }
  1204. ],
  1205. deployPath: [
  1206. { required: true, message: '请输入部署到 170/showcase 下的目标路径名称', trigger: 'change' }
  1207. ]
  1208. }
  1209. }
  1210. },
  1211. methods: {
  1212. // 部署
  1213. doDeploy() {
  1214. let self = this;
  1215.  
  1216. this.$refs['form'].validate((valid) => {
  1217. if (valid) {
  1218. this.dialogDeployVisible = false;
  1219. this.depDialogVisible = true;
  1220. this.loading = true;
  1221. // 部署
  1222. this.getDeployInfo({ type: '1', frame: this.form.frame, deployPath: this.form.deployPath }, (data)=> {
  1223. this.loading = false;
  1224. this.depDialogVisible = false;
  1225.  
  1226. if(!data.custom.text){
  1227.  
  1228. this.data = data.custom.pageTreeData;
  1229. this.projectFtpUrl = data.custom.projectRootPath;
  1230. this.supportDeploy = data.custom.supportDeploy;
  1231.  
  1232. this.$message({
  1233. type: 'success',
  1234. message: '部署成功!'
  1235. });
  1236. // 打开查看弹窗
  1237. this.viewProject();
  1238. this.toggleViewButton(true);
  1239.  
  1240. } else {
  1241. this.$message({
  1242. type: 'error',
  1243. message: data.custom.text
  1244. });
  1245. }
  1246. });
  1247. } else {
  1248. console.log('error submit!!');
  1249. return false;
  1250. }
  1251. });
  1252. },
  1253. // 项目部署
  1254. getDeployInfo(params, callback) {
  1255. const author = document.querySelector('#account a').innerText.trim().substring(4);
  1256. const projectName = document.getElementsByName('Title')[0].value.trim();
  1257. const projectGitUrl = document.getElementsByName('SourceCode')[0].value.trim();
  1258.  
  1259. if(typeof params == 'function') {
  1260. callback = params;
  1261. params = null;
  1262. }
  1263. if(author && author.length && projectGitUrl) {
  1264. fetch('http://192.168.219.170:3008/api/getDeployInfo', {
  1265. method: 'POST',
  1266. // 允许跨域请求
  1267. mode: 'cors',
  1268. headers: {
  1269. 'Accept': 'application/json',
  1270. 'Content-Type': 'application/json'
  1271. },
  1272. body: JSON.stringify({//post请求参数
  1273. params: {
  1274. "type": (params && params.type !== undefined) ? params.type : '0',// 0 代表查看, 1代表部署
  1275. "deployMan": author, // 部署人姓名
  1276. "projectName": projectName, // 项目名称
  1277. "projectGitUrl": projectGitUrl,
  1278. "frame": (params && params.frame) ? params.frame : undefined,
  1279. "deployPath": (params && params.deployPath) ? params.deployPath : undefined // 部署的目标目录
  1280. }
  1281. })
  1282. })
  1283. .then(response => response.text())
  1284. .then((result) => {
  1285. var data = JSON.parse(result);
  1286. callback && callback(data);
  1287. })
  1288. .catch(error => {
  1289. this.depDialogVisible = false;
  1290. this.dialogVisible = false;
  1291. this.$message({
  1292. type: 'error',
  1293. message: '系统故障,请联系管理员。'
  1294. });
  1295. console.error(error);
  1296. });
  1297. } else {
  1298. this.$message({
  1299. type: 'error',
  1300. message: '本页面不支持查看和部署,请先登录。'
  1301. });
  1302. console.error('部署信息请求参数error');
  1303. }
  1304. },
  1305. // 查看项目
  1306. viewProject () {
  1307. this.dialogVisible = true;
  1308. let self = this;
  1309.  
  1310. if(this.data) {
  1311. this.loadingTree = false;
  1312. } else {
  1313. this.loadingTree = true;
  1314. // 发送ajax请求,查看是否进行过部署
  1315. this.getDeployInfo((data)=> {
  1316. // 有部署信息,直接赋值,
  1317. if(data) {
  1318. self.projectIsDeployed = true;
  1319. self.data = data.custom.pageTreeData;
  1320. self.projectFtpUrl = data.custom.projectRootPath;
  1321. self.supportDeploy = data.custom.supportDeploy;
  1322. self.loadingTree = false;
  1323.  
  1324. self.toggleViewButton(true);
  1325.  
  1326. }
  1327. });
  1328. }
  1329. },
  1330. handleNodeClick(data) {
  1331. console.log(data);
  1332. if(data.type === 'folder') {
  1333. return false;
  1334. }
  1335. var self = this;
  1336. var entry = data.entry;
  1337. self.clickNodeEntry = entry;
  1338. if(self.projectFtpUrl) {
  1339. window.open('http://192.168.219.170' + self.projectFtpUrl + data.entry);
  1340. self.clickNodeEntry = null;
  1341. } else {
  1342. if(this.supportDeploy === false) {
  1343. this.$message({
  1344. type: 'error',
  1345. message: '当前项目暂时只支持查看,请耐心等待功能升级。'
  1346. });
  1347. self.clickNodeEntry = null;
  1348. return false;
  1349. }
  1350.  
  1351. this.$confirm('资源未部署,部署至 170 服务器后可查看,是否部署?')
  1352. .then(_ => {
  1353.  
  1354. this.dialogDeployVisible = true;
  1355. })
  1356. .catch(_ => {});
  1357. }
  1358. },
  1359. // svn 需要制定目录名称,showDeployPath
  1360. showDialog(showDeployPath) {
  1361. this.showDeployPath = showDeployPath;
  1362. this.dialogDeployVisible = true;
  1363. },
  1364. // 查看按钮显影控制
  1365. toggleViewButton(show) {
  1366. const $viewBtn = jQuery('#view');
  1367.  
  1368. if(!$viewBtn.length) {
  1369. return;
  1370. }
  1371.  
  1372. if(show) {
  1373. $viewBtn.removeClass('hidden');
  1374. } else {
  1375. $viewBtn.addClass('hidden');
  1376. }
  1377. }
  1378. },
  1379. mounted() {
  1380. const $btnDeloy = jQuery('#deploy');
  1381. const $btnView = jQuery('#view');
  1382.  
  1383. // 绑定vue组件外的事件
  1384. $btnDeloy.on('click', function() {
  1385. // 源码地址和项目名称判断
  1386. const sourceInput = document.getElementsByName('SourceCode');
  1387. const projectNameInput = document.getElementsByName('Title');
  1388.  
  1389. let sourceInputVal = sourceInput[0].value.trim(),
  1390. projectNameInputVal = projectNameInput[0].value.trim();
  1391.  
  1392. const gitpattern = /^http:\/\/192\.168/;
  1393. const svnpattern = /^svn:\/\/192\.168/;
  1394. const sourcepattern = /^(svn:\/\/192\.168|http:\/\/192\.168)/;
  1395.  
  1396. if (!sourceInputVal) {
  1397. vueInstance.$message({
  1398. type: 'error',
  1399. message: '请输入源码地址!'
  1400. });
  1401. return
  1402. }
  1403.  
  1404. if (!sourcepattern.test(sourceInputVal)) {
  1405. vueInstance.$message({
  1406. type: 'error',
  1407. message: '请输入准确的源码 gitlab 或 svn 地址!'
  1408. });
  1409. return
  1410. }
  1411.  
  1412. if (svnpattern.test(sourceInputVal) && !projectNameInputVal) {
  1413. vueInstance.$message({
  1414. type: 'error',
  1415. message: ' svn 仓库地址部署需要填写项目(案例)名称!'
  1416. });
  1417. return
  1418. }
  1419.  
  1420. vueInstance.showDialog(svnpattern.test(sourceInputVal));
  1421. });
  1422. // 查看项目
  1423. $btnView.on('click', function() {
  1424. vueInstance.viewProject();
  1425. });
  1426.  
  1427. },
  1428. template: `<div id="my-form">
  1429. <el-dialog title="部署提示" width="640px" :visible.sync="dialogDeployVisible">
  1430. <el-alert
  1431. title="此操作将把 GitLab / SVN 资源打包部署至 170 服务器,已部署过的项目会进行覆盖部署,是否继续?"
  1432. type="warning" :closable="false" style="margin-bottom: 20px;">
  1433. </el-alert>
  1434. <el-form :model="form" ref="form" :rules="rules">
  1435. <el-form-item label="框架类型" :label-width="formLabelWidth" prop="frame">
  1436. <el-select v-model="form.frame" placeholder="请框架类型" style="width:380px;">
  1437. <el-option v-for="item in framework" :key="item.value" :label="item.label" :value="item.value"></el-option>
  1438. </el-select>
  1439. </el-form-item>
  1440. <el-form-item label="部署路径" :label-width="formLabelWidth" prop="deployPath" v-if="showDeployPath">
  1441. <el-input v-model="form.deployPath" placeholder="请输入部署至服务器 170/showcase 下的目标路径名称" style="width:380px;"></el-input>
  1442. </el-form-item>
  1443. </el-form>
  1444. <div slot="footer" class="dialog-footer">
  1445. <el-button @click="dialogDeployVisible = false">取 消</el-button>
  1446. <el-button type="primary" @click="doDeploy">确 定</el-button>
  1447. </div>
  1448. </el-dialog>
  1449. <el-dialog
  1450. title="部署"
  1451. width="420px"
  1452. :visible.sync="depDialogVisible">
  1453. <div class="deploy-body"
  1454. style="height: 306px;"
  1455. v-loading="loading"
  1456. element-loading-text="正在打包部署至 170 服务器,请耐心等待"
  1457. element-loading-spinner="el-icon-loading">
  1458. </div>
  1459. </el-dialog>
  1460. <el-dialog
  1461. title="目录结构"
  1462. width="900px"
  1463. :append-to-body="true"
  1464. :visible.sync="dialogVisible">
  1465. <el-tree
  1466. class="filter-tree"
  1467. :data="data"
  1468. :props="defaultProps"
  1469. node-key="id"
  1470. default-expand-all
  1471. @node-click="handleNodeClick"
  1472. v-loading="loadingTree"
  1473. element-loading-background="rgba(255, 255, 255, 1)"
  1474. element-loading-text="拼命加载中......"
  1475. ref="tree">
  1476. </el-tree>
  1477. </el-dialog>
  1478. </div>`
  1479. });
  1480.  
  1481. // 将占位元素追加到 body 元素中
  1482. jQuery('.form-container').after(vueInstance.$el);
  1483. };
  1484. })();
  1485.  
  1486. // 新建项目提示
  1487. (function() {
  1488. 'use strict';
  1489. let regs = [/^http:\/\/192\.168\.0\.200\/projects\/new/];
  1490. let match = false;
  1491.  
  1492. for(let r = 0, lr = regs.length; r < lr; r++) {
  1493. if(regs[r].test(location.href)) {
  1494. match = true;
  1495. break;
  1496. }
  1497. }
  1498.  
  1499. if(!match) {
  1500. return;
  1501. }
  1502.  
  1503. // 等待页面加载完成
  1504. window.addEventListener('load', function() {
  1505. const $projectName = jQuery('#project_name');
  1506. const $projectDescription = jQuery('#project_description');
  1507. const $check = jQuery('#project_visibility_level_10');
  1508.  
  1509. if($projectName && $projectName.length) {
  1510. $projectName.attr('placeholder', '以需求或项目管理系统中的项目名称为准')
  1511. }
  1512.  
  1513. if($projectDescription && $projectDescription.length) {
  1514. let date = new Date();
  1515. const imgEl = document.querySelector('.header-user-avatar');
  1516. let name = imgEl ? imgEl.getAttribute('alt') : '张三';
  1517. $projectDescription.attr('placeholder', 'YYYY-M-D,张三,UI:https://oa.epoint.com.cn/interaction-design-portal/portal/pages/casestemplates/casetemplatesdetail?guid=');
  1518. $projectDescription.val(date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate() + ','+ name +',UI:https://oa.epoint.com.cn/interaction-design-portal/portal/pages/casestemplates/casetemplatesdetail?guid=');
  1519.  
  1520. // 增加主题表单
  1521. var themeHtml = '<div class="row">\
  1522. <div class="form-group col-md-9">\
  1523. <label class="label-bold" for="project_topics">主题</label>\
  1524. <input value="" maxlength="2000" class="form-control gl-form-input" placeholder="业务条线(政务服务|一网协同...),项目类型(网站|业务系统|中屏可视化...),关键字(f950sp2|gojs|vue...)" size="2000" type="text" name="project[topics]" id="project_topics" data-is-dirty-submit-input="true" data-dirty-submit-original-value="">\
  1525. <p class="form-text text-muted">用逗号分隔主题。</p>\
  1526. <p class="form-text text-muted">业务条线:政务服务、大数据、一网统管、一网协同、智能设备、电子交易、数字建设、公共安全、支撑产品;</p>\
  1527. <p class="form-text text-muted">项目类型:网站、业务系统、智能设备、大屏可视化、中屏可视化、在线表单;</p>\
  1528. <p class="form-text text-muted">关键字:f942f951f950sp2f9x2.0f9x1.0、骨架、vuereact、单页、gojselementAntDesign、全景、关系图、流程图、响应式、svg、视频、miniuiegisegis3d、高德、百度、超图、three、主题、瀑布流、上传、自定义用户控件等;</p>\
  1529. </div></div>';
  1530.  
  1531. $projectDescription.closest('.form-group').after(themeHtml);
  1532. // 规避中文,
  1533. $projectDescription.blur(function(event) {
  1534. this.value = this.value.replace(/,/g, ',').replace(/&isfwqfb=1/g, '');
  1535. // 日期转换
  1536. this.value = convertDateFormat(this.value);
  1537. });
  1538.  
  1539. var $theme = jQuery('#project_topics');
  1540.  
  1541. $theme.blur(function(event) {
  1542. this.value = this.value.replaceAll(',', ',');
  1543. });
  1544. }
  1545.  
  1546. if($check && $check.length) {
  1547. $check.trigger('click');
  1548. }
  1549. });
  1550.  
  1551. })();
  1552.  
  1553. // 通过 oa 首页中转,跳过跨站访问的限制
  1554. (function(){
  1555. 'use strict';
  1556. let regs = [/^https:\/\/oa\.epoint\.com\.cn\/epointoa9\/frame\/fui\/pages\/themes\/aide/];
  1557. let match = false;
  1558.  
  1559. for(let r = 0, lr = regs.length; r < lr; r++) {
  1560. if(regs[r].test(location.href)) {
  1561. match = true;
  1562. break;
  1563. }
  1564. }
  1565.  
  1566. if(!match) {
  1567. return;
  1568. }
  1569.  
  1570. let redirectUlr = gitlabUtil.getUrlParameters().redirect;
  1571.  
  1572. if(redirectUlr) {
  1573. window.location.href = redirectUlr;
  1574. }
  1575. })();
  1576.  
  1577. // 设计门户瀑布流页面,查找对应项目
  1578. (function(){
  1579. 'use strict';
  1580. let regs = [/^https:\/\/oa\.epoint\.com\.cn\/interaction-design-portal\/portal\/pages\/casestemplates\/casetemplateslist/];
  1581. let match = false;
  1582.  
  1583. for(let r = 0, lr = regs.length; r < lr; r++) {
  1584. if(regs[r].test(location.href)) {
  1585. match = true;
  1586. break;
  1587. }
  1588. }
  1589.  
  1590. if(!match) {
  1591. return;
  1592. }
  1593.  
  1594. let projectName = location.href.split('projectname');
  1595.  
  1596. window.addEventListener('load', function() {
  1597. if(projectName[1]) {
  1598. projectName = decodeURIComponent(projectName[1]);
  1599.  
  1600. const $input = jQuery('#search-input');
  1601. const $searchBtn = jQuery('.search-icon');
  1602.  
  1603. setTimeout(() => {
  1604. $input.val(projectName);
  1605. $searchBtn.trigger('click');
  1606. }, 1000);
  1607. }
  1608. });
  1609.  
  1610. })();