GitLab Assistant

GitLab Viewer Publish and Deploy Project!

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

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