efe7eebb128d0887308c67a7008a1e153fad7d1f.svn-base 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. <template>
  2. <div :id="containerId" style="position: relative">
  3. <!-- ---------------------------- begin 图片左右换位置 ------------------------------------- -->
  4. <div class="movety-container" :style="{top:top+'px',left:left+'px',display:moveDisplay}"
  5. style="padding:0 8px;position: absolute;z-index: 91;height: 32px;width: 104px;text-align: center;">
  6. <div :id="containerId+'-mover'" :class="showMoverTask?'uploadty-mover-mask':'movety-opt'"
  7. style="margin-top: 12px">
  8. <a @click="moveLast" style="margin: 0 5px;">
  9. <a-icon type="arrow-left" style="color: #fff;font-size: 16px"/>
  10. </a>
  11. <a @click="moveNext" style="margin: 0 5px;">
  12. <a-icon type="arrow-right" style="color: #fff;font-size: 16px"/>
  13. </a>
  14. </div>
  15. </div>
  16. <!-- ---------------------------- end 图片左右换位置 ------------------------------------- -->
  17. <a-upload
  18. name="file"
  19. :multiple="multiple"
  20. :action="uploadAction"
  21. :headers="headers"
  22. :data="{'biz':bizPath}"
  23. :fileList="fileList"
  24. :beforeUpload="doBeforeUpload"
  25. @change="handleChange"
  26. :disabled="disabled"
  27. :returnUrl="returnUrl"
  28. :listType="complistType"
  29. @preview="handlePreview"
  30. :class="{'uploadty-disabled':disabled}">
  31. <template>
  32. <div v-if="isImageComp">
  33. <a-icon type="plus"/>
  34. <div class="ant-upload-text">{{ text }}</div>
  35. </div>
  36. <a-button v-else-if="buttonVisible">
  37. <a-icon type="upload"/>
  38. {{ text }}
  39. </a-button>
  40. </template>
  41. </a-upload>
  42. <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
  43. <img alt="example" style="width: 100%" :src="previewImage"/>
  44. </a-modal>
  45. </div>
  46. </template>
  47. <script>
  48. import Vue from 'vue'
  49. import {ACCESS_TOKEN} from "@/store/mutation-types"
  50. import {getFileAccessHttpUrl} from '@/api/manage';
  51. const FILE_TYPE_ALL = "all"
  52. const FILE_TYPE_IMG = "image"
  53. const FILE_TYPE_TXT = "file"
  54. const uidGenerator = () => {
  55. return '-' + parseInt(Math.random() * 10000 + 1, 10);
  56. }
  57. const getFileName = (path) => {
  58. if (path.lastIndexOf("\\") >= 0) {
  59. let reg = new RegExp("\\\\", "g");
  60. path = path.replace(reg, "/");
  61. }
  62. return path.substring(path.lastIndexOf("/") + 1);
  63. }
  64. export default {
  65. name: 'JUpload',
  66. data() {
  67. return {
  68. uploadAction: window._CONFIG['domianURL'] + "/sys/common/upload",
  69. headers: {},
  70. fileList: [],
  71. newFileList: [],
  72. uploadGoOn: true,
  73. previewVisible: false,
  74. //---------------------------- begin 图片左右换位置 -------------------------------------
  75. previewImage: '',
  76. containerId: '',
  77. top: '',
  78. left: '',
  79. moveDisplay: 'none',
  80. showMoverTask: false,
  81. moverHold: false,
  82. currentImg: ''
  83. //---------------------------- end 图片左右换位置 -------------------------------------
  84. }
  85. },
  86. props: {
  87. text: {
  88. type: String,
  89. required: false,
  90. default: "点击上传"
  91. },
  92. fileType: {
  93. type: String,
  94. required: false,
  95. default: FILE_TYPE_ALL
  96. },
  97. /*这个属性用于控制文件上传的业务路径*/
  98. bizPath: {
  99. type: String,
  100. required: false,
  101. default: "temp"
  102. },
  103. value: {
  104. type: [String, Array],
  105. required: false
  106. },
  107. // update-begin- --- author:wangshuai ------ date:20190929 ---- for:Jupload组件增加是否能够点击
  108. disabled: {
  109. type: Boolean,
  110. required: false,
  111. default: false
  112. },
  113. // update-end- --- author:wangshuai ------ date:20190929 ---- for:Jupload组件增加是否能够点击
  114. //此属性被废弃了
  115. triggerChange: {
  116. type: Boolean,
  117. required: false,
  118. default: false
  119. },
  120. /**
  121. * update -- author:lvdandan -- date:20190219 -- for:Jupload组件增加是否返回url,
  122. * true:仅返回url
  123. * false:返回fileName filePath fileSize
  124. */
  125. returnUrl: {
  126. type: Boolean,
  127. required: false,
  128. default: true
  129. },
  130. number: {
  131. type: Number,
  132. required: false,
  133. default: 0
  134. },
  135. buttonVisible: {
  136. type: Boolean,
  137. required: false,
  138. default: true
  139. },
  140. multiple: {
  141. type: Boolean,
  142. default: true
  143. },
  144. beforeUpload: {
  145. type: Function
  146. },
  147. },
  148. watch: {
  149. value: {
  150. immediate: true,
  151. handler() {
  152. let val = this.value
  153. if (val instanceof Array) {
  154. if (this.returnUrl) {
  155. this.initFileList(val.join(','))
  156. } else {
  157. this.initFileListArr(val);
  158. }
  159. } else {
  160. this.initFileList(val)
  161. }
  162. }
  163. }
  164. },
  165. computed: {
  166. isImageComp() {
  167. return this.fileType === FILE_TYPE_IMG
  168. },
  169. complistType() {
  170. return this.fileType === FILE_TYPE_IMG ? 'picture-card' : 'text'
  171. }
  172. },
  173. created() {
  174. const token = Vue.ls.get(ACCESS_TOKEN);
  175. //---------------------------- begin 图片左右换位置 -------------------------------------
  176. this.headers = {"X-Access-Token": token};
  177. this.containerId = 'container-ty-' + new Date().getTime();
  178. //---------------------------- end 图片左右换位置 -------------------------------------
  179. },
  180. methods: {
  181. initFileListArr(val) {
  182. if (!val || val.length == 0) {
  183. this.fileList = [];
  184. return;
  185. }
  186. let fileList = [];
  187. for (var a = 0; a < val.length; a++) {
  188. let url = getFileAccessHttpUrl(val[a].filePath);
  189. fileList.push({
  190. uid: uidGenerator(),
  191. name: val[a].fileName,
  192. status: 'done',
  193. url: url,
  194. response: {
  195. status: "history",
  196. message: val[a].filePath
  197. }
  198. })
  199. }
  200. this.fileList = fileList
  201. },
  202. initFileList(paths) {
  203. if (!paths || paths.length == 0) {
  204. //return [];
  205. // update-begin- --- author:os_chengtgen ------ date:20190729 ---- for:issues:326,Jupload组件初始化bug
  206. this.fileList = [];
  207. return;
  208. // update-end- --- author:os_chengtgen ------ date:20190729 ---- for:issues:326,Jupload组件初始化bug
  209. }
  210. let fileList = [];
  211. let arr = paths.split(",")
  212. for (var a = 0; a < arr.length; a++) {
  213. let url = getFileAccessHttpUrl(arr[a]);
  214. fileList.push({
  215. uid: uidGenerator(),
  216. name: getFileName(arr[a]),
  217. status: 'done',
  218. url: url,
  219. response: {
  220. status: "history",
  221. message: arr[a]
  222. }
  223. })
  224. }
  225. this.fileList = fileList
  226. },
  227. handlePathChange() {
  228. let uploadFiles = this.fileList
  229. let path = ''
  230. if (!uploadFiles || uploadFiles.length == 0) {
  231. path = ''
  232. }
  233. let arr = [];
  234. for (var a = 0; a < uploadFiles.length; a++) {
  235. // update-begin-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错
  236. if (uploadFiles[a].status === 'done') {
  237. arr.push(uploadFiles[a].response.message)
  238. } else {
  239. return;
  240. }
  241. // update-end-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错
  242. }
  243. if (arr.length > 0) {
  244. path = arr.join(",")
  245. }
  246. this.$emit('change', path);
  247. },
  248. doBeforeUpload(file) {
  249. this.uploadGoOn = true
  250. var fileType = file.type;
  251. if (this.fileType === FILE_TYPE_IMG) {
  252. if (fileType.indexOf('image') < 0) {
  253. this.$message.warning('请上传图片');
  254. this.uploadGoOn = false
  255. return false;
  256. }
  257. }
  258. // 扩展 beforeUpload 验证
  259. if (typeof this.beforeUpload === 'function') {
  260. return this.beforeUpload(file)
  261. }
  262. return true
  263. },
  264. handleChange(info) {
  265. console.log("--文件列表改变--")
  266. if (!info.file.status && this.uploadGoOn === false) {
  267. info.fileList.pop();
  268. }
  269. let fileList = info.fileList
  270. if (info.file.status === 'done') {
  271. if (this.number > 0) {
  272. fileList = fileList.slice(-this.number);
  273. }
  274. if (info.file.response.success) {
  275. fileList = fileList.map((file) => {
  276. if (file.response) {
  277. let reUrl = file.response.message;
  278. file.url = getFileAccessHttpUrl(reUrl);
  279. }
  280. return file;
  281. });
  282. }
  283. //this.$message.success(`${info.file.name} 上传成功!`);
  284. } else if (info.file.status === 'error') {
  285. this.$message.error(`${info.file.name} 上传失败.`);
  286. } else if (info.file.status === 'removed') {
  287. this.handleDelete(info.file)
  288. }
  289. this.fileList = fileList
  290. if (info.file.status === 'done' || info.file.status === 'removed') {
  291. //returnUrl为true时仅返回文件路径
  292. if (this.returnUrl) {
  293. this.handlePathChange()
  294. } else {
  295. //returnUrl为false时返回文件名称、文件路径及文件大小
  296. this.newFileList = [];
  297. for (var a = 0; a < fileList.length; a++) {
  298. // update-begin-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错
  299. if (fileList[a].status === 'done') {
  300. var fileJson = {
  301. fileName: fileList[a].name,
  302. filePath: fileList[a].response.message,
  303. fileSize: fileList[a].size
  304. };
  305. this.newFileList.push(fileJson);
  306. } else {
  307. return;
  308. }
  309. // update-end-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错
  310. }
  311. this.$emit('change', this.newFileList);
  312. }
  313. }
  314. },
  315. handleDelete(file) {
  316. //如有需要新增 删除逻辑
  317. console.log(file)
  318. },
  319. handlePreview(file) {
  320. debugger;
  321. if (this.fileType === FILE_TYPE_IMG) {
  322. this.previewImage = file.url || file.thumbUrl;
  323. this.previewVisible = true;
  324. } else {
  325. if(file.name.endsWith('.pdf')){
  326. let pdfUrl = window._CONFIG['domianURL'] + "/generic/web/viewer.html?file=" + encodeURIComponent(file.url);
  327. window.open(pdfUrl,"_blank");
  328. } else if(file.name.endsWith('.jpg')||file.name.endsWith('.png')||file.name.endsWith('.bmp')){
  329. this.previewImage = file.url || file.thumbUrl;
  330. this.previewVisible = true;
  331. }else{
  332. location.href = file.url;
  333. }
  334. }
  335. },
  336. handleCancel() {
  337. this.previewVisible = false;
  338. },
  339. //---------------------------- begin 图片左右换位置 -------------------------------------
  340. moveLast() {
  341. //console.log(ev)
  342. //console.log(this.fileList)
  343. //console.log(this.currentImg)
  344. let index = this.getIndexByUrl();
  345. if (index == 0) {
  346. this.$message.warn('未知的操作')
  347. } else {
  348. let curr = this.fileList[index].url;
  349. let last = this.fileList[index - 1].url;
  350. let arr = []
  351. for (let i = 0; i < this.fileList.length; i++) {
  352. if (i == index - 1) {
  353. arr.push(curr)
  354. } else if (i == index) {
  355. arr.push(last)
  356. } else {
  357. arr.push(this.fileList[i].url)
  358. }
  359. }
  360. this.currentImg = last
  361. this.$emit('change', arr.join(','))
  362. }
  363. },
  364. moveNext() {
  365. let index = this.getIndexByUrl();
  366. if (index == this.fileList.length - 1) {
  367. this.$message.warn('已到最后~')
  368. } else {
  369. let curr = this.fileList[index].url;
  370. let next = this.fileList[index + 1].url;
  371. let arr = []
  372. for (let i = 0; i < this.fileList.length; i++) {
  373. if (i == index + 1) {
  374. arr.push(curr)
  375. } else if (i == index) {
  376. arr.push(next)
  377. } else {
  378. arr.push(this.fileList[i].url)
  379. }
  380. }
  381. this.currentImg = next
  382. this.$emit('change', arr.join(','))
  383. }
  384. },
  385. getIndexByUrl() {
  386. for (let i = 0; i < this.fileList.length; i++) {
  387. if (this.fileList[i].url === this.currentImg || encodeURI(this.fileList[i].url) === this.currentImg) {
  388. return i;
  389. }
  390. }
  391. return -1;
  392. }
  393. },
  394. mounted() {
  395. const moverObj = document.getElementById(this.containerId + '-mover');
  396. if (moverObj) {
  397. moverObj.addEventListener('mouseover', () => {
  398. this.moverHold = true
  399. this.moveDisplay = 'block';
  400. });
  401. moverObj.addEventListener('mouseout', () => {
  402. this.moverHold = false
  403. this.moveDisplay = 'none';
  404. });
  405. }
  406. let picList = document.getElementById(this.containerId) ? document.getElementById(this.containerId).getElementsByClassName('ant-upload-list-picture-card') : [];
  407. if (picList && picList.length > 0) {
  408. picList[0].addEventListener('mouseover', (ev) => {
  409. ev = ev || window.event;
  410. let target = ev.target || ev.srcElement;
  411. if ('ant-upload-list-item-info' == target.className) {
  412. this.showMoverTask = false
  413. let item = target.parentElement
  414. this.left = item.offsetLeft
  415. this.top = item.offsetTop + item.offsetHeight - 50;
  416. this.moveDisplay = 'block';
  417. this.currentImg = target.getElementsByTagName('img')[0].src
  418. }
  419. });
  420. picList[0].addEventListener('mouseout', (ev) => {
  421. ev = ev || window.event;
  422. let target = ev.target || ev.srcElement;
  423. //console.log('移除',target)
  424. if ('ant-upload-list-item-info' == target.className) {
  425. this.showMoverTask = true
  426. setTimeout(() => {
  427. if (this.moverHold === false)
  428. this.moveDisplay = 'none';
  429. }, 100)
  430. }
  431. if ('ant-upload-list-item ant-upload-list-item-done' == target.className || 'ant-upload-list ant-upload-list-picture-card' == target.className) {
  432. this.moveDisplay = 'none';
  433. }
  434. })
  435. //---------------------------- end 图片左右换位置 -------------------------------------
  436. }
  437. },
  438. model: {
  439. prop: 'value',
  440. event: 'change'
  441. }
  442. }
  443. </script>
  444. <style lang="less">
  445. .uploadty-disabled {
  446. .ant-upload-list-item {
  447. .anticon-close {
  448. display: none;
  449. }
  450. .anticon-delete {
  451. display: none;
  452. }
  453. }
  454. }
  455. //---------------------------- begin 图片左右换位置 -------------------------------------
  456. .uploadty-mover-mask {
  457. background-color: rgba(0, 0, 0, 0.5);
  458. opacity: .8;
  459. color: #fff;
  460. height: 28px;
  461. line-height: 28px;
  462. }
  463. //---------------------------- end 图片左右换位置 -------------------------------------
  464. </style>