lj-img-pro.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. <!--图片展示器,集下载、删除等辅助功能(集成了龙嘉协议获取图片的方式)-->
  2. <template>
  3. <div class="lj-img-pro lj-picture_and_video" :class="{'round': round}">
  4. <van-image
  5. class="img-pro-box"
  6. :src="currentSrc"
  7. :fit="fit"
  8. :round="round"
  9. :radius="RadiusValue"
  10. @click="imageClick"
  11. >
  12. <template v-slot:error>
  13. <i v-if="!error" class="loading-icon iconfont icon-a-Image2"></i>
  14. <i v-else class="error-icon iconfont icon-ImageError"></i>
  15. </template>
  16. </van-image>
  17. <slot name="bottom-nav" v-if="showfilename">
  18. <div class="bottom-nav">
  19. <div class="name text-ellipsis-one">
  20. {{ fileName }}
  21. </div>
  22. </div>
  23. </slot>
  24. <div class="bottom-nav-status" v-if="downloadbtn && (downloading || dlSuccess != 0)" :class="{'show': downloadbtn && (downloading || dlSuccess != 0)}">
  25. <!-- <div class="error-refresh" v-if="error && !delbtn"></div> -->
  26. <div class="download" :class="{'del-item': delbtn, 'dl-success': dlSuccess == 1, 'dl-fail': dlSuccess == 2}">
  27. <template v-if="downloading">
  28. <van-loading class="video-loading" size="14" color="#fff">
  29. <span class="bottom-nav-text">
  30. 保存中
  31. </span>
  32. </van-loading>
  33. </template>
  34. <template v-else-if="dlSuccess != 0">
  35. <i v-if="dlSuccess == 1" class="iconfont icon-check"></i>
  36. <i v-else class="iconfont icon-jinggao"></i>
  37. </template>
  38. </div>
  39. </div>
  40. <div v-if="downloadbtn || delbtn || error || loading" class="control-bar">
  41. <van-tag
  42. v-if="loading"
  43. class="tag-item"
  44. :class="{'loading': loading}"
  45. round
  46. >
  47. <van-loading color="#8E8E93" size="14" />
  48. </van-tag>
  49. <van-tag
  50. v-else
  51. class="tag-item"
  52. :class="{'del-item': delbtn, 'download-item': downloadbtn, 'error-item': error && !delbtn, 'loading': downloading}"
  53. round
  54. @click.stop="handleBottomNav"
  55. >
  56. <template v-if="delbtn">
  57. <i class="iconfont icon-close"></i>
  58. </template>
  59. <template v-else-if="error && !delbtn">
  60. <i class="iconfont icon-ic_refresh"></i>
  61. </template>
  62. <template v-else-if="downloading">
  63. <van-loading color="#8E8E93" size="14" />
  64. </template>
  65. <template v-else-if="downloadbtn">
  66. <i class="iconfont icon-save1"></i>
  67. </template>
  68. </van-tag>
  69. </div>
  70. </div>
  71. </template>
  72. <script>
  73. export default {
  74. name: "lj-img-pro",
  75. props: {
  76. // 龙嘉协议的图片md5值
  77. md5: {
  78. Type: String,
  79. default: ""
  80. },
  81. // 普通http路径
  82. src: {
  83. Type: String,
  84. default: ""
  85. },
  86. fit:{
  87. Type:String,
  88. default:"contain"
  89. // contain 保持宽高缩放图片,使图片的长边能完全显示出来
  90. // cover 保持宽高缩放图片,使图片的短边能完全显示出来,裁剪长边
  91. // fill 拉伸图片,使图片填满元素
  92. // none 保持图片原有尺寸
  93. // scale-down 取none或contain中较小的一个
  94. },
  95. round:{
  96. Type:Boolean,
  97. default:false
  98. },
  99. Radius:{
  100. Type:String,
  101. default:'0'
  102. },
  103. fileType: String,
  104. fileName: String,
  105. delbtn: { // 是否显示删除按钮
  106. type: Boolean,
  107. default: false
  108. },
  109. downloadbtn: {// 是否显示下载按钮
  110. type: Boolean,
  111. default: false
  112. },
  113. showfilename: {// 是否显示文件名
  114. type: Boolean,
  115. default: false
  116. },
  117. loadPostion: { // loading位置。默认右上,
  118. type: String,
  119. default: ''
  120. }
  121. },
  122. data() {
  123. return {
  124. currentSrc: "",
  125. RadiusValue: "",
  126. downloading: false,
  127. dlSuccess: 0, // 是否下载成功: 0,未操作,1:成功,2:失败
  128. loading: false,
  129. error: false,
  130. }
  131. },
  132. computed: {
  133. realFileType() {
  134. let type = this.fileType || (this.fileFj ? this.fileFj.fileType : "");
  135. if (type) {
  136. let dotIndex = type.indexOf('.');
  137. if (dotIndex >= 0) {
  138. type = type.substring(type.indexOf('.') + 1);
  139. }
  140. }
  141. return type.replace(/^\s+|\s+$/g,"");;
  142. },
  143. },
  144. mounted() {
  145. if(this.Round){
  146. this.RadiusValue = '50%';
  147. }
  148. else{
  149. this.RadiusValue = this.Radius;
  150. }
  151. this.refreshImg();
  152. },
  153. methods: {
  154. refreshImg() {
  155. this.error = false;
  156. this.loading = true;
  157. let self = this;
  158. if (this.src) {
  159. //this.currentSrc = this.src;
  160. api.imageCache({
  161. url: this.src,
  162. policy: "cache_only",
  163. thumbnail: false
  164. }, function (ret, err) {
  165. self.loading = false;
  166. if (!err) {
  167. self.getBase64(ret.url)
  168. }else{
  169. self.error = true;
  170. alert(JSON.stringify(err));
  171. }
  172. console.log(ret.status + "\r\n" + ret.url);
  173. })
  174. } else if (this.md5) {
  175. $lj.getCacheDir(function (cacheDir) {
  176. let path = cacheDir + "/" + self.md5;
  177. var fs = $lj.getFileHelperModule();
  178. console.warn("refreshImg getCacheDir:" + path);
  179. fs.exist({
  180. path: path
  181. }, function (ret, err) {
  182. if (ret.exist) {
  183. self.loading = false;
  184. self.getBase64(path);
  185. } else {
  186. $lj.postLJRequest("GetCacheFile", {filemd5: self.md5}, function (ret) {
  187. var cacheDir = $lj.constant.cacheDir;
  188. let newPath = cacheDir + "/" + self.md5;
  189. if (ret.filedata !== self.md5) {
  190. let oldPath = cacheDir + "/" + ret.filedata;
  191. console.error(`!!!!!!!! lj-img:renaming ${ret.filedata} to ${self.md5} !!!`);
  192. fs.rename({
  193. oldPath: oldPath,
  194. newPath: newPath
  195. }, function (ret, err) {
  196. if (ret.status) {
  197. self.getBase64(newPath);
  198. } else {
  199. self.error = true;
  200. console.error("图片重命名: " + JSON.stringify(err));
  201. }
  202. });
  203. } else {
  204. self.getBase64(newPath);
  205. }
  206. self.loading = false;
  207. }, function(ret) {
  208. self.error = true;
  209. self.loading = false;
  210. }, true);
  211. }
  212. });
  213. });
  214. }
  215. },
  216. imageClick(item) {
  217. if (this.error) {
  218. // 加载失败
  219. this.refreshImg();
  220. return;
  221. }
  222. this.$emit('image-click', item);
  223. },
  224. getBase64(path) {
  225. this.currentSrc = path;
  226. return;
  227. //热加载时使用
  228. console.log(path);
  229. var trans = $lj.getBase64TranModule();
  230. let self = this;
  231. trans.decodeImgToBase64({
  232. imgPath: path
  233. }, function (ret, err) {
  234. if (ret.status) {
  235. console.log(JSON.stringify(ret));
  236. var str = ret.base64Str;
  237. self.currentSrc = "data:image/png;base64," + str;
  238. } else {
  239. alert(JSON.stringify(err));
  240. }
  241. });
  242. },
  243. handleBottomNav () {
  244. if (this.error && !this.delbtn) {
  245. // 加载失败
  246. this.refreshImg();
  247. return;
  248. }
  249. if (this.downloadbtn) {
  250. this.download();
  251. } else {
  252. this.$emit('bottom-nav')
  253. }
  254. },
  255. checkFile(oldPath, callback) {
  256. let self = this;
  257. var fs = $lj.getFileHelperModule();
  258. $lj.getCacheDir(function (cacheDir) {
  259. let newPath = cacheDir + "/topic/" + self.md5 + "." + self.realFileType;
  260. // console.warn("refreshImg getCacheDir:" + cacheDir);
  261. fs.exist({
  262. path: newPath
  263. }, function (ret, err) {
  264. // console.log('newPath ret :>>>>>>>>>>>>>>>>>>>>>', JSON.stringify(ret));
  265. if (ret.exist) {
  266. callback(newPath);
  267. return;
  268. } else {
  269. fs.copyTo({
  270. oldPath: oldPath,
  271. newPath: cacheDir + "/topic"
  272. }, function(ret, err) {
  273. // console.log('copyTo ret :>>>>>>>>>>>>>>>>>>>>>', JSON.stringify(ret));
  274. if (ret.status) {
  275. fs.rename({
  276. oldPath: cacheDir + "/topic/" + self.md5,
  277. newPath: newPath
  278. }, function (ret, err) {
  279. if (ret.status) {
  280. callback(newPath);
  281. } else {
  282. console.error("图片重命名: " + JSON.stringify(err));
  283. }
  284. });
  285. } else {
  286. alert('copyTo操作失败,保存中断');
  287. }
  288. });
  289. }
  290. });
  291. });
  292. },
  293. _fnDownLoad(path, callback) {
  294. api.saveMediaToAlbum({
  295. path: path
  296. }, (ret, err) => {
  297. if (ret && ret.status) {
  298. this.$toast.success('保存成功');
  299. this.dlSuccess = 1;
  300. } else {
  301. alert('保存失败');
  302. this.dlSuccess = 2;
  303. }
  304. callback();
  305. setTimeout(() => {
  306. this.dlSuccess = 0;
  307. }, 1500);
  308. });
  309. },
  310. download(){
  311. if (this.downloading || this.dlSuccess != 0) {
  312. return;
  313. }
  314. this.downloading = true;
  315. if (this.src) {
  316. this._fnDownLoad(this.currentSrc, () => {
  317. this.downloading = false;
  318. })
  319. } else if (this.md5) {
  320. this.checkFile(this.currentSrc, (newPath) => {
  321. this._fnDownLoad(newPath, () => {
  322. this.downloading = false;
  323. })
  324. });
  325. }
  326. },
  327. },
  328. watch:{
  329. md5(newVal,oldVal){
  330. if (newVal !== oldVal){
  331. this.refreshImg();
  332. }
  333. },
  334. src(newVal,oldVal){
  335. if (newVal !== oldVal){
  336. this.refreshImg();
  337. }
  338. }
  339. }
  340. }
  341. </script>
  342. <style lang="less">
  343. .lj-img-pro {
  344. &.round {
  345. border-radius: 50%;
  346. overflow: hidden;
  347. }
  348. .img-pro-box {
  349. display: block;
  350. width: 100%;
  351. height: 100%;
  352. .loading-icon {
  353. font-size: 32px;
  354. color: @light-system-gray4;
  355. opacity: 0.3;
  356. }
  357. .error-icon {
  358. font-size: 32px;
  359. color: @light-system-red;
  360. opacity: 0.6;
  361. }
  362. }
  363. }
  364. </style>