混凝土运输管理微信小程序、替班
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

288 lines
5.7 KiB

2 weeks ago
  1. <template>
  2. <view class="input-image-container">
  3. <view class="upload-area" v-if="showUploadBtn">
  4. <view class="upload-btn" @click="chooseImage">
  5. <view v-if="showPlaceholder" class="placeholder-area" :style="{ height: placeholderHeight }">
  6. <!-- 占位区域 -->
  7. </view>
  8. <view class="upload-icon">
  9. <image style="width:110rpx;height:110rpx" src="/static/re/ico.png" />
  10. </view>
  11. <view v-if="hasImage" class="image-preview" :style="{ height: imageHeight }">
  12. <image
  13. :style="{ height: imageDisplayHeight }"
  14. :src="imageUrl"
  15. mode="scaleToFill"
  16. class="preview-image"
  17. />
  18. </view>
  19. </view>
  20. </view>
  21. <!-- 显示已上传的图片 -->
  22. <view v-if="showImageOnly" class="image-display" :style="{ height: 'auto' }">
  23. <image
  24. :style="{ height: 'auto' }"
  25. :src="displayImageUrl"
  26. mode="widthFix"
  27. class="display-image"
  28. />
  29. </view>
  30. <!-- 多图上传模式 -->
  31. <view v-if="multiple" class="multiple-upload">
  32. <uv-upload
  33. :fileList="fileList"
  34. :multiple="true"
  35. :maxCount="maxCount"
  36. :width="uploadWidth"
  37. :height="uploadHeight"
  38. @afterRead="afterRead"
  39. @delete="deleteImage"
  40. >
  41. <image
  42. src="/static/re/ico.png"
  43. mode="aspectFill"
  44. :style="{ width: uploadWidth, height: uploadHeight }"
  45. />
  46. </uv-upload>
  47. </view>
  48. </view>
  49. </template>
  50. <script>
  51. export default {
  52. name: 'InputImage',
  53. props: {
  54. // 是否显示上传按钮
  55. showUploadBtn: {
  56. type: Boolean,
  57. default: true
  58. },
  59. // 是否显示占位区域
  60. showPlaceholder: {
  61. type: Boolean,
  62. default: false
  63. },
  64. // 占位区域高度
  65. placeholderHeight: {
  66. type: String,
  67. default: '200rpx'
  68. },
  69. // 是否有图片
  70. hasImage: {
  71. type: Boolean,
  72. default: false
  73. },
  74. // 图片URL
  75. imageUrl: {
  76. type: String,
  77. default: ''
  78. },
  79. // 图片高度
  80. imageHeight: {
  81. type: String,
  82. default: '300rpx'
  83. },
  84. // 图片显示高度
  85. imageDisplayHeight: {
  86. type: String,
  87. default: '300rpx'
  88. },
  89. // 只显示图片模式
  90. showImageOnly: {
  91. type: Boolean,
  92. default: false
  93. },
  94. // 显示的图片URL
  95. displayImageUrl: {
  96. type: String,
  97. default: ''
  98. },
  99. // 是否多图上传
  100. multiple: {
  101. type: Boolean,
  102. default: false
  103. },
  104. // 最大上传数量
  105. maxCount: {
  106. type: Number,
  107. default: 3
  108. },
  109. // 上传区域宽度
  110. uploadWidth: {
  111. type: String,
  112. default: '180rpx'
  113. },
  114. // 上传区域高度
  115. uploadHeight: {
  116. type: String,
  117. default: '180rpx'
  118. },
  119. // 文件列表
  120. fileList: {
  121. type: Array,
  122. default: () => []
  123. }
  124. },
  125. data() {
  126. return {
  127. internalFileList: []
  128. }
  129. },
  130. mounted() {
  131. this.internalFileList = [...this.fileList];
  132. },
  133. watch: {
  134. fileList: {
  135. handler(newVal) {
  136. this.internalFileList = [...newVal];
  137. },
  138. deep: true
  139. }
  140. },
  141. methods: {
  142. // 选择图片
  143. chooseImage() {
  144. uni.chooseImage({
  145. count: 1,
  146. sizeType: ['compressed'],
  147. sourceType: ['album', 'camera'],
  148. success: (res) => {
  149. const tempFilePath = res.tempFilePaths[0];
  150. this.$emit('imageSelected', tempFilePath);
  151. // 模拟上传到OSS
  152. this.uploadToOss(tempFilePath);
  153. },
  154. fail: (err) => {
  155. console.error('选择图片失败:', err);
  156. uni.showToast({
  157. title: '选择图片失败',
  158. icon: 'none'
  159. });
  160. }
  161. });
  162. },
  163. // 模拟上传到OSS
  164. uploadToOss(filePath) {
  165. uni.showLoading({
  166. title: '上传中...'
  167. });
  168. // 模拟上传过程
  169. setTimeout(() => {
  170. uni.hideLoading();
  171. // 模拟生成OSS URL
  172. const mockOssUrl = `https://relief.oss-cn-hangzhou.aliyuncs.com/mock_${Date.now()}.jpg`;
  173. this.$emit('uploadSuccess', {
  174. localPath: filePath,
  175. ossUrl: mockOssUrl
  176. });
  177. uni.showToast({
  178. title: '上传成功',
  179. icon: 'success'
  180. });
  181. }, 1000); // 模拟1秒上传时间
  182. },
  183. // 多图上传后处理
  184. afterRead(e) {
  185. const files = Array.isArray(e.file) ? e.file : [e.file];
  186. files.forEach(file => {
  187. this.uploadToOssMultiple(file.url);
  188. });
  189. },
  190. // 模拟多图上传到OSS
  191. uploadToOssMultiple(filePath) {
  192. // 模拟上传过程
  193. setTimeout(() => {
  194. // 模拟生成OSS URL
  195. const mockOssUrl = `https://relief.oss-cn-hangzhou.aliyuncs.com/mock_${Date.now()}.jpg`;
  196. this.internalFileList.push({
  197. url: mockOssUrl
  198. });
  199. this.$emit('update:fileList', this.internalFileList);
  200. this.$emit('multipleUploadSuccess', this.internalFileList);
  201. }, 500); // 模拟0.5秒上传时间
  202. },
  203. // 删除图片
  204. deleteImage(e) {
  205. this.internalFileList.splice(e.index, 1);
  206. this.$emit('update:fileList', this.internalFileList);
  207. this.$emit('imageDeleted', e.index);
  208. }
  209. }
  210. }
  211. </script>
  212. <style scoped lang="scss">
  213. .input-image-container {
  214. position: relative;
  215. }
  216. .upload-area {
  217. position: relative;
  218. }
  219. .upload-btn {
  220. position: relative;
  221. border: 2rpx dashed #ddd;
  222. border-radius: 10rpx;
  223. padding: 20rpx;
  224. text-align: center;
  225. background-color: #fafafa;
  226. transition: all 0.3s;
  227. &:active {
  228. background-color: #f0f0f0;
  229. }
  230. }
  231. .placeholder-area {
  232. width: 100%;
  233. background-color: #f5f5f5;
  234. border-radius: 8rpx;
  235. margin-bottom: 20rpx;
  236. }
  237. .upload-icon {
  238. margin-bottom: 20rpx;
  239. }
  240. .image-preview {
  241. width: 100%;
  242. border-radius: 8rpx;
  243. overflow: hidden;
  244. .preview-image {
  245. width: 100%;
  246. border-radius: 8rpx;
  247. }
  248. }
  249. .image-display {
  250. width: 100%;
  251. border-radius: 8rpx;
  252. overflow: hidden;
  253. .display-image {
  254. width: 100%;
  255. border-radius: 8rpx;
  256. }
  257. }
  258. .multiple-upload {
  259. padding: 20rpx;
  260. background-color: #fff;
  261. border-radius: 10rpx;
  262. }
  263. </style>