TraceUpdate.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. <template>
  2. <div>
  3. <div>
  4. <Navbar title="编辑任务" :is-go-back="true" />
  5. <div v-if="traceDto != null">
  6. <div class="form-group">
  7. <label for="exampleInputEmail1">标题</label>
  8. <input
  9. id="exampleInputEmail1"
  10. v-model="traceDto.summary"
  11. autocomplete="off"
  12. type="text"
  13. class="form-control"
  14. placeholder="标题"
  15. />
  16. </div>
  17. <div class="form-group">
  18. <label for="exampleInputPassword1">内容</label>
  19. <div id="summernote" />
  20. </div>
  21. <div class="form-group">
  22. <label for="projectName">项目</label>
  23. <select
  24. id="projectName"
  25. v-model="traceDto.projectId"
  26. class="form-control"
  27. @change="changeProjectSelected()"
  28. >
  29. <option
  30. v-for="project in projectItemUserListProject"
  31. :key="project.id"
  32. :value="project.projectItemId"
  33. >
  34. {{ project.projectItemName }}
  35. </option>
  36. </select>
  37. </div>
  38. <AudioField
  39. :class-name="className"
  40. :src-array="srcArray"
  41. :is-readonly="'false'"
  42. @handle-stop="handelEndRecord"
  43. @delete-audio-src="deleteAudioSrc"
  44. />
  45. <div class="form-group">
  46. <label for="projectName">时间节点</label>
  47. <Treeselect
  48. ref="treeSelect"
  49. :multiple="false"
  50. :options="projectTaskDtos"
  51. />
  52. </div>
  53. <div class="form-group">
  54. <label for="receiveUserId">责任人</label>
  55. <select
  56. id="receiveUserId"
  57. v-model="traceDto.receiveUserId"
  58. class="form-control"
  59. >
  60. <option value="" />
  61. <option
  62. v-for="user in projectItemUserListUser"
  63. :key="user.userId"
  64. :value="user.userId"
  65. >
  66. {{ user.userName }}
  67. </option>
  68. </select>
  69. </div>
  70. <div class="form-group">
  71. <label>完成时间</label>
  72. <a-config-provider :locale="locale">
  73. <a-date-picker
  74. v-model:value="planFinishedDate"
  75. style="width: 100%"
  76. show-time
  77. format="YYYY-MM-DD HH:mm:ss"
  78. :show-now="false"
  79. placeholder="请选择完成日期"
  80. />
  81. </a-config-provider>
  82. <!-- <Date
  83. v-model="traceDto.planFinishedDate"
  84. style="width: 100%"
  85. /> -->
  86. </div>
  87. <button
  88. style="width: 100%; background-color: #007aff; color: white"
  89. type="button"
  90. class="btn btn-blue search-button"
  91. @click="updateTrace()"
  92. >
  93. 保存
  94. </button>
  95. </div>
  96. </div>
  97. <Loading v-if="loading" />
  98. </div>
  99. </template>
  100. <script>
  101. import TraceResource from './TraceResource.js';
  102. import Common from '../common/Common.js';
  103. import UpladFile from '../widget/UpladFile.js';
  104. import TraceCommon from './TraceCommon.js';
  105. import { Notify } from 'pc-component-v3';
  106. import Treeselect from '../widget/TreeSelect.vue';
  107. import AudioField from '../widget/AudioField.vue';
  108. import { message } from 'ant-design-vue';
  109. import zhCN from 'ant-design-vue/es/locale/zh_CN';
  110. import dayjs from 'dayjs';
  111. import 'dayjs/locale/zh-cn';
  112. import weekday from 'dayjs/plugin/weekday';
  113. import localeData from 'dayjs/plugin/localeData';
  114. dayjs.extend(weekday);
  115. dayjs.extend(localeData);
  116. dayjs.locale('zh-cn');
  117. export default {
  118. components: {
  119. UpladFile,
  120. Treeselect,
  121. AudioField,
  122. },
  123. data: function () {
  124. return {
  125. traceId: '',
  126. traceDto: {},
  127. className: 'com.leanwo.prodog.Trace',
  128. projectItemUserListUser: [],
  129. projectItemUserListProject: [],
  130. summernoteInitSuccess: false, // summernote初始化成功
  131. projectTaskDtos: [], //项目任务时间点
  132. isflag: true,
  133. srcArray: [],
  134. loading: false,
  135. locale: zhCN,
  136. planFinishedDate: '',
  137. };
  138. },
  139. watch: {
  140. 'traceDto.projectId': function (curVal, oldVal) {
  141. var _self = this;
  142. _self.queryProjectTaskDtoByProjectId();
  143. if (_self.isflag) {
  144. _self.$refs.treeSelect.setValue(undefined);
  145. } else {
  146. _self.$refs.treeSelect.setValue(_self.traceDto.projectTaskId);
  147. }
  148. _self.isflag = true;
  149. },
  150. },
  151. mounted: function () {
  152. var _self = this;
  153. this.initProject();
  154. this.initContext();
  155. this.isflag = false;
  156. },
  157. beforeUnmount: function () {
  158. if (this.summernoteInitSuccess == true) {
  159. $('#summernote').summernote('destroy');
  160. }
  161. //界面销毁时,修改插入连接的display属性
  162. $('.note-link-popover').removeAttr('style');
  163. },
  164. methods: {
  165. /**
  166. * 删除语音
  167. * @param {Object} index
  168. */
  169. deleteAudioSrc: function (index) {
  170. var _self = this;
  171. _self.srcArray.splice(index, 1);
  172. _self.traceDto.audioSrcs = JSON.stringify(_self.srcArray);
  173. },
  174. /**
  175. * 录音停止之后
  176. * @param {Object} param
  177. */
  178. handelEndRecord: function (param) {
  179. var _self = this;
  180. if (param.fileName != undefined) {
  181. _self.srcArray.push(param.fileName);
  182. _self.traceDto.audioSrcs = JSON.stringify(_self.srcArray);
  183. }
  184. },
  185. back: function () {
  186. history.back();
  187. },
  188. updateTrace: function () {
  189. var _self = this;
  190. _self.traceDto.detail = $('#summernote').summernote('code');
  191. _self.traceDto.projectTaskId = _self.$refs.treeSelect.getValue();
  192. if (_self.planFinishedDate != undefined && _self.planFinishedDate != '') {
  193. _self.traceDto.planFinishedDate = _self.dateConvert(
  194. _self.planFinishedDate,
  195. ); //完成时间
  196. }
  197. if (_self.traceDto.summary != '' && _self.traceDto.summary != undefined) {
  198. _self.loading = true;
  199. $.ajax({
  200. url: Common.getApiURL('TraceResource/updateTrace'),
  201. type: 'post',
  202. contentType: 'application/json',
  203. data: JSON.stringify(_self.traceDto),
  204. beforeSend: function (request) {
  205. Common.addTokenToRequest(request);
  206. },
  207. success: function (data) {
  208. Notify.success('提示', '修改成功!');
  209. _self.loading = false;
  210. _self.back();
  211. },
  212. error: function (XMLHttpRequest, textStatus, errorThrown) {
  213. _self.loading = false;
  214. Common.processException(XMLHttpRequest, textStatus, errorThrown);
  215. },
  216. });
  217. } else {
  218. Notify.error('提示', '标题不能为空!');
  219. }
  220. },
  221. //图片上传
  222. sendFile: function (file, editor, $editable) {
  223. var _self = this;
  224. UpladFile.photoCompress(
  225. file,
  226. {
  227. quality: 0.2,
  228. },
  229. function (base64Codes) {
  230. var bl = UpladFile.convertBase64UrlToBlob(base64Codes);
  231. var rst = new FormData();
  232. rst.append('images', bl, 'file_' + Date.parse(new Date()) + '.jpg');
  233. rst.append('className', _self.className);
  234. $.ajax({
  235. url: Common.getApiURL('file/imageUpload'),
  236. type: 'post',
  237. data: rst,
  238. contentType: false,
  239. processData: false,
  240. beforeSend: function (request) {
  241. Common.addTokenToRequest(request);
  242. },
  243. success: function (data) {
  244. if (data.errorCode == 0) {
  245. if (data.datas) {
  246. var imageName = data.datas[0];
  247. // 方法1: 直接插入图片,由于图片不能加载,导致导致插入失败。
  248. // $("#summernote").summernote('insertImage', Common.getResourceUrl("image", _self.className, imageName), 'image name');
  249. // 方法2:创建img节点,然后插入<img>节点,可以插入,但是图片没有显示,点击一下code,然后就显示了。
  250. // var node = document.createElement('img') // 创建节点,用于包裹视频,再加这一层是方便调视频样式
  251. // node.setAttribute("authSrc", Common.getResourceUrl("image", _self.className, imageName));
  252. // node.setAttribute("is", "auth-img");
  253. // $("#summernote").summernote('insertNode', node);
  254. // 方法3:重新给code赋值,此时丢失了鼠标焦点,此时不满足要求。
  255. // var get_code = $('#summernote').summernote('code');
  256. // $('#summernote').summernote('code', get_code);
  257. // 方法4:插入文本(尝试失败)
  258. //let imageText = "<img is='auth-img' authSrc='" + Common.getResourceUrl("image", _self.className, imageName) + "'/>";
  259. //$('#summernote').summernote('insertText', imageText);
  260. // 方法5: 插入div,div中嵌入img,测试OK
  261. // var node = document.createElement('div') // 创建节点,用于包裹视频,再加这一层是方便调视频样式
  262. // node.innerHTML = "<img is='auth-img' authSrc='" + Common.getResourceUrl("image", _self.className, imageName) + "' />";
  263. // $("#summernote").summernote('insertNode', node);
  264. $('#summernote').summernote(
  265. 'insertImage',
  266. Common.getResourceUrl('image', _self.className, imageName),
  267. 'image name',
  268. );
  269. }
  270. } else {
  271. message.error(data.errorMessage);
  272. }
  273. },
  274. error: function () {
  275. Notify.error('提示', '上传失败!');
  276. return;
  277. },
  278. });
  279. return rst.file;
  280. },
  281. );
  282. },
  283. /**
  284. * 初始化项目
  285. */
  286. initProject: function () {
  287. var _self = this;
  288. _self.projectItemUserListProject.splice(
  289. 0,
  290. _self.projectItemUserListProject.length,
  291. );
  292. $.ajax({
  293. url: Common.getApiURL('ProjectItemUserResource/listByUserId'), //通过用户Id查找有权操作的项目
  294. type: 'get',
  295. dataType: 'json',
  296. contentType: 'application/json',
  297. beforeSend: function (request) {
  298. Common.addTokenToRequest(request);
  299. },
  300. success: function (data) {
  301. for (var index = 0; index < data.length; index++) {
  302. _self.projectItemUserListProject[index] = data[index];
  303. // _self.$set(_self.projectItemUserListProject, index, data[index]);
  304. }
  305. },
  306. error: function (XMLHttpRequest, textStatus, errorThrown) {
  307. Common.processException(XMLHttpRequest, textStatus, errorThrown);
  308. },
  309. });
  310. },
  311. /**
  312. * 项目选择
  313. * @author ZhangTeng 20190213
  314. */
  315. changeProjectSelected: function () {
  316. var _self = this;
  317. var count = 0;
  318. _self.projectItemUserListUser.splice(
  319. 0,
  320. _self.projectItemUserListUser.length,
  321. );
  322. if (_self.traceDto == null || _self.traceDto.projectId == null) {
  323. return;
  324. }
  325. $.ajax({
  326. url: Common.getApiURL('ProjectItemUserResource/listByProjectItemId'), //通过项目Id查找有权操作的项目的用户
  327. type: 'get',
  328. dataType: 'json',
  329. contentType: 'application/json',
  330. data: { projectItemId: _self.traceDto.projectId },
  331. beforeSend: function (request) {
  332. Common.addTokenToRequest(request);
  333. },
  334. success: function (data) {
  335. for (var index = 0; index < data.length; index++) {
  336. _self.projectItemUserListUser[index] = data[index];
  337. // _self.$set(_self.projectItemUserListUser, index, data[index]);
  338. }
  339. },
  340. error: function (XMLHttpRequest, textStatus, errorThrown) {
  341. Common.processException(XMLHttpRequest, textStatus, errorThrown);
  342. },
  343. });
  344. },
  345. //初始化数据
  346. initContext: function () {
  347. var _self = this;
  348. _self.traceId = this.$route.params.traceId;
  349. if (_self.traceId != null && _self.traceId != '') {
  350. TraceResource.uniqueByTraceId(_self.traceId).then(
  351. successData => {
  352. _self.traceDto = successData;
  353. _self.planFinishedDate = dayjs(successData.planFinishedDate,'YYYY-MM-DD HH:mm:ss');
  354. if (
  355. successData != undefined &&
  356. successData.audioSrcs != undefined
  357. ) {
  358. _self.srcArray = JSON.parse(successData.audioSrcs);
  359. }
  360. _self.changeProjectSelected();
  361. $('#summernote').summernote({
  362. toolbar: [
  363. [
  364. 'insert',
  365. [
  366. 'link',
  367. 'picture',
  368. 'video',
  369. 'audio',
  370. 'hr',
  371. 'table', //插件
  372. 'fontname',
  373. 'fontsize',
  374. 'color',
  375. 'bold',
  376. 'italic',
  377. 'underline',
  378. 'strikethrough',
  379. 'clear', //字体样式
  380. 'style',
  381. 'ol',
  382. 'ul',
  383. 'paragraph',
  384. 'height', //段落样式
  385. 'fullscreen',
  386. 'codeview',
  387. 'undo',
  388. 'redo',
  389. 'help', //Misc
  390. ],
  391. ],
  392. ],
  393. height: 400,
  394. minHeight: 300,
  395. maxHeight: 500,
  396. focus: true,
  397. lang: 'zh-CN',
  398. callbacks: {
  399. onImageUpload: function (files, editor, $editable) {
  400. _self.sendFile(files[0], editor, $editable);
  401. },
  402. },
  403. });
  404. if (_self.traceDto != null) {
  405. $('#summernote').summernote('code', _self.traceDto.detail);
  406. }
  407. _self.summernoteInitSuccess = true;
  408. },
  409. errorData => {
  410. Common.processException(errorData);
  411. },
  412. );
  413. }
  414. },
  415. /**
  416. * 根据项目id查询项目任务时间节点
  417. * @author GuoZhiBo 20191010
  418. */
  419. queryProjectTaskDtoByProjectId: function () {
  420. var _self = this;
  421. $.ajax({
  422. url: Common.getApiURL(
  423. 'ProjectTaskResource/queryProjectTaskDtoByProjectId',
  424. ),
  425. type: 'get',
  426. dataType: 'json',
  427. contentType: 'application/json',
  428. data: {
  429. projectId: _self.traceDto.projectId,
  430. },
  431. beforeSend: function (request) {
  432. Common.addTokenToRequest(request);
  433. },
  434. success: function (data) {
  435. _self.projectTaskDtos = data;
  436. console.log(_self.projectTaskDtos);
  437. },
  438. error: function (XMLHttpRequest, textStatus, errorThrown) {
  439. Common.processException(XMLHttpRequest, textStatus, errorThrown);
  440. },
  441. });
  442. },
  443. // 日期处理函数
  444. plusZero: function (n) {
  445. return n >= 10 ? n : '0' + n;
  446. },
  447. dateConvert: function (dateStr) {
  448. const date = new Date(dateStr);
  449. const year = date.getFullYear();
  450. const month = date.getMonth() + 1;
  451. const day = date.getDate();
  452. const hour = date.getHours();
  453. const minute = date.getMinutes();
  454. const second = date.getSeconds();
  455. return (
  456. year +
  457. '-' +
  458. this.plusZero(month) +
  459. '-' +
  460. this.plusZero(day) +
  461. ' ' +
  462. this.plusZero(hour) +
  463. ':' +
  464. this.plusZero(minute) +
  465. ':' +
  466. this.plusZero(second)
  467. );
  468. },
  469. },
  470. };
  471. </script>
  472. <style scoped>
  473. </style>