From d3fd4b0ab851bab89c30c199e27245f7f45f1c0e Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期六, 08 十一月 2025 08:01:12 +0800
Subject: [PATCH] feat:实现了微信上传图片
---
app/pages/task/detail.vue | 519 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 518 insertions(+), 1 deletions(-)
diff --git a/app/pages/task/detail.vue b/app/pages/task/detail.vue
index 8598db2..3932e66 100644
--- a/app/pages/task/detail.vue
+++ b/app/pages/task/detail.vue
@@ -194,6 +194,35 @@
</view>
</view>
+ <!-- 闄勪欢淇℃伅 -->
+ <view class="detail-section">
+ <view class="section-title">
+ 浠诲姟闄勪欢
+ <button class="upload-btn" @click="showUploadDialog">涓婁紶闄勪欢</button>
+ </view>
+ <view v-if="attachmentList && attachmentList.length > 0">
+ <view class="attachment-item" v-for="(item, index) in attachmentList" :key="item.attachmentId">
+ <view class="attachment-info">
+ <view class="attachment-category">
+ <text class="category-tag">{{ getCategoryName(item.attachmentCategory) }}</text>
+ </view>
+ <view class="attachment-name">{{ item.fileName }}</view>
+ <view class="attachment-meta">
+ <text class="upload-time">{{ formatTime(item.uploadTime) }}</text>
+ <text class="file-size">{{ formatFileSize(item.fileSize) }}</text>
+ </view>
+ </view>
+ <view class="attachment-actions">
+ <button class="action-btn view-btn" @click="viewAttachment(item)">鏌ョ湅</button>
+ <button class="action-btn delete-btn" @click="deleteAttachment(item.attachmentId, index)">鍒犻櫎</button>
+ </view>
+ </view>
+ </view>
+ <view v-else class="no-attachment">
+ <text>鏆傛棤闄勪欢</text>
+ </view>
+ </view>
+
<!-- 绂忕杞︿换鍔$壒鏈変俊鎭� -->
<view class="detail-section" v-if="taskDetail.taskType === 'WELFARE' && taskDetail.welfareInfo">
<view class="section-title">涔樺淇℃伅</view>
@@ -314,18 +343,66 @@
<!-- 宸插畬鎴�/宸插彇娑�: 涓嶆樉绀烘寜閽� -->
</view>
+
+ <!-- 闄勪欢涓婁紶瀵硅瘽妗� -->
+ <uni-popup ref="uploadPopup" type="bottom">
+ <view class="upload-dialog">
+ <view class="dialog-header">
+ <text class="dialog-title">涓婁紶闄勪欢</text>
+ <uni-icons type="closeempty" size="24" @click="closeUploadDialog"></uni-icons>
+ </view>
+ <view class="dialog-content">
+ <view class="form-item">
+ <view class="form-label">闄勪欢鍒嗙被</view>
+ <picker @change="onCategoryChange" :value="selectedCategoryIndex" :range="categoryList" range-key="label">
+ <view class="picker-value">
+ {{ categoryList[selectedCategoryIndex].label }}
+ <uni-icons type="arrowdown" size="16"></uni-icons>
+ </view>
+ </picker>
+ </view>
+ <view class="form-item">
+ <view class="form-label">閫夋嫨鍥剧墖</view>
+ <button class="choose-image-btn" @click="chooseImage">
+ <uni-icons type="image" size="20"></uni-icons>
+ <text>鐐瑰嚮閫夋嫨</text>
+ </button>
+ </view>
+ <view class="preview-area" v-if="tempImagePath">
+ <image :src="tempImagePath" mode="aspectFit" class="preview-image"></image>
+ </view>
+ </view>
+ <view class="dialog-footer">
+ <button class="cancel-btn" @click="closeUploadDialog">鍙栨秷</button>
+ <button class="confirm-btn" @click="confirmUpload" :disabled="!tempImagePath">纭畾涓婁紶</button>
+ </view>
+ </view>
+ </uni-popup>
</view>
</template>
<script>
import { getTask, changeTaskStatus } from '@/api/task'
+ import { getAttachmentList, uploadAttachmentFromWechat, deleteAttachment, getWechatAccessToken } from '@/api/task'
import { formatDateTime } from '@/utils/common'
export default {
data() {
return {
taskDetail: null,
- taskId: null
+ taskId: null,
+ attachmentList: [],
+ categoryList: [
+ { label: '鐭ユ儏鍚屾剰涔�', value: '1' },
+ { label: '鐥呬汉璧勬枡', value: '2' },
+ { label: '鎿嶄綔璁板綍', value: '3' },
+ { label: '鍑鸿溅鍓�', value: '4' },
+ { label: '鍑鸿溅鍚�', value: '5' },
+ { label: '绯诲畨鍏ㄥ甫', value: '6' }
+ ],
+ selectedCategoryIndex: 0,
+ tempImagePath: null,
+ isWechatMiniProgram: false // 鏄惁鏄井淇″皬绋嬪簭鐜
}
},
computed: {
@@ -387,6 +464,12 @@
onLoad(options) {
this.taskId = options.id
this.loadTaskDetail()
+ this.loadAttachmentList()
+
+ // 妫�娴嬫槸鍚︽槸寰俊灏忕▼搴忕幆澧�
+ // #ifdef MP-WEIXIN
+ this.isWechatMiniProgram = true
+ // #endif
},
methods: {
// 鍔犺浇浠诲姟璇︽儏
@@ -592,6 +675,254 @@
})
}
})
+ },
+
+ // 鍔犺浇闄勪欢鍒楄〃
+ loadAttachmentList() {
+ if (!this.taskId) {
+ return
+ }
+
+ getAttachmentList(this.taskId).then(response => {
+ this.attachmentList = response.data || response || []
+ }).catch(error => {
+ console.error('鍔犺浇闄勪欢鍒楄〃澶辫触:', error)
+ })
+ },
+
+ // 鏄剧ず涓婁紶瀵硅瘽妗�
+ showUploadDialog() {
+ this.selectedCategoryIndex = 0
+ this.tempImagePath = null
+ this.$refs.uploadPopup.open()
+ },
+
+ // 鍏抽棴涓婁紶瀵硅瘽妗�
+ closeUploadDialog() {
+ this.$refs.uploadPopup.close()
+ },
+
+ // 鍒嗙被閫夋嫨鍙樺寲
+ onCategoryChange(e) {
+ this.selectedCategoryIndex = e.detail.value
+ },
+
+ // 閫夋嫨鍥剧墖
+ chooseImage() {
+ const that = this
+ uni.chooseImage({
+ count: 1,
+ sizeType: ['compressed'],
+ sourceType: ['album', 'camera'],
+ success: function(res) {
+ that.tempImagePath = res.tempFilePaths[0]
+ },
+ fail: function(err) {
+ console.error('閫夋嫨鍥剧墖澶辫触:', err)
+ that.$modal.showToast('閫夋嫨鍥剧墖澶辫触')
+ }
+ })
+ },
+
+ // 纭涓婁紶
+ confirmUpload() {
+ if (!this.tempImagePath) {
+ this.$modal.showToast('璇峰厛閫夋嫨鍥剧墖')
+ return
+ }
+
+ const that = this
+ const category = this.categoryList[this.selectedCategoryIndex].value
+
+ // 寰俊灏忕▼搴忕幆澧冿細鍏堣幏鍙朅ccessToken锛屽啀涓婁紶鍒板井淇℃湇鍔″櫒锛屾渶鍚庢彁浜ediaId鍒板悗绔�
+ // #ifdef MP-WEIXIN
+ if (this.isWechatMiniProgram) {
+ uni.showLoading({
+ title: '涓婁紶涓�...'
+ })
+
+ // 绗竴姝ワ細浠庡悗绔幏鍙朅ccessToken
+ getWechatAccessToken().then(tokenResponse => {
+ // 鎺ュ彛杩斿洖鏍煎紡锛歿"msg":"token鍊�","code":200}
+ console.log('鑾峰彇AccessToken鎴愬姛:', tokenResponse)
+ const accessToken = tokenResponse.msg || tokenResponse.data || tokenResponse
+ if (!accessToken) {
+ uni.hideLoading()
+ that.$modal.showToast('鑾峰彇AccessToken澶辫触')
+ console.error('鑾峰彇AccessToken澶辫触锛屽搷搴旀暟鎹�:', tokenResponse)
+ return
+ }
+
+ console.log('鑾峰彇鍒癆ccessToken:', accessToken)
+
+ // 绗簩姝ワ細涓婁紶鍒板井淇℃湇鍔″櫒
+ const uploadUrl = `https://api.weixin.qq.com/cgi-bin/media/upload?access_token=${accessToken}&type=image`
+
+ uni.uploadFile({
+ url: uploadUrl,
+ filePath: that.tempImagePath,
+ name: 'media',
+ success: function(res) {
+ console.log('寰俊涓婁紶鍝嶅簲:', res)
+ try {
+ const data = JSON.parse(res.data)
+ if (data.media_id) {
+ // 绗笁姝ワ細鎻愪氦mediaId鍒板悗绔�
+ uploadAttachmentFromWechat(that.taskId, data.media_id, category).then(response => {
+ uni.hideLoading()
+ that.$modal.showToast('涓婁紶鎴愬姛')
+ that.closeUploadDialog()
+ that.loadAttachmentList()
+ }).catch(error => {
+ uni.hideLoading()
+ console.error('鎻愪氦mediaId澶辫触:', error)
+ that.$modal.showToast('涓婁紶澶辫触锛�' + (error.msg || '璇烽噸璇�'))
+ })
+ } else {
+ uni.hideLoading()
+ const errMsg = data.errmsg || '鏈煡閿欒'
+ console.error('寰俊杩斿洖閿欒:', data)
+ that.$modal.showToast('寰俊涓婁紶澶辫触锛�' + errMsg)
+ }
+ } catch (e) {
+ uni.hideLoading()
+ console.error('瑙f瀽寰俊鍝嶅簲澶辫触:', e, res.data)
+ that.$modal.showToast('涓婁紶澶辫触锛氬搷搴旇В鏋愰敊璇�')
+ }
+ },
+ fail: function(err) {
+ uni.hideLoading()
+ console.error('涓婁紶鍒板井淇″け璐�:', err)
+ that.$modal.showToast('涓婁紶澶辫触锛�' + (err.errMsg || '璇锋鏌ョ綉缁�'))
+ }
+ })
+ }).catch(error => {
+ uni.hideLoading()
+ console.error('鑾峰彇AccessToken澶辫触:', error)
+ that.$modal.showToast('鑾峰彇AccessToken澶辫触')
+ })
+ return
+ }
+ // #endif
+
+ // 闈炲井淇″皬绋嬪簭鐜锛氱洿鎺ヤ笂浼犲埌鍚庣鏈嶅姟鍣�
+ uni.showLoading({
+ title: '涓婁紶涓�...'
+ })
+
+ uni.uploadFile({
+ url: that.$baseUrl + '/task/attachment/upload/' + that.taskId,
+ filePath: that.tempImagePath,
+ name: 'file',
+ formData: {
+ 'category': category
+ },
+ header: {
+ 'Authorization': 'Bearer ' + uni.getStorageSync('token')
+ },
+ success: function(uploadRes) {
+ uni.hideLoading()
+
+ if (uploadRes.statusCode === 200) {
+ const result = JSON.parse(uploadRes.data)
+ if (result.code === 200) {
+ that.$modal.showToast('涓婁紶鎴愬姛')
+ that.closeUploadDialog()
+ that.loadAttachmentList()
+ } else {
+ that.$modal.showToast(result.msg || '涓婁紶澶辫触')
+ }
+ } else {
+ that.$modal.showToast('涓婁紶澶辫触')
+ }
+ },
+ fail: function(err) {
+ uni.hideLoading()
+ console.error('涓婁紶澶辫触:', err)
+ that.$modal.showToast('涓婁紶澶辫触')
+ }
+ })
+ },
+
+ // 鏌ョ湅闄勪欢
+ viewAttachment(item) {
+ // 濡傛灉鏄浘鐗囷紝浣跨敤鍥剧墖棰勮
+ const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp']
+ const fileExt = item.fileName.split('.').pop().toLowerCase()
+
+ if (imageTypes.includes(fileExt)) {
+ // 鏋勫缓鍥剧墖璁块棶鍦板潃
+ // 濡傛灉鏄痜ilePath鏄畬鏁磋矾寰勶紝闇�瑕侀�氳繃涓嬭浇鎺ュ彛璁块棶
+ const imageUrl = this.$baseUrl + '/task/attachment/download/' + item.attachmentId
+
+ // 寰俊灏忕▼搴忎腑棰勮鍥剧墖
+ // #ifdef MP-WEIXIN
+ // 寰俊灏忕▼搴忛渶瑕佸厛涓嬭浇鍒版湰鍦板啀棰勮
+ uni.showLoading({ title: '鍔犺浇涓�...' })
+ uni.downloadFile({
+ url: imageUrl,
+ success: function(res) {
+ uni.hideLoading()
+ if (res.statusCode === 200) {
+ uni.previewImage({
+ urls: [res.tempFilePath],
+ current: res.tempFilePath
+ })
+ } else {
+ uni.showToast({ title: '鍔犺浇鍥剧墖澶辫触', icon: 'none' })
+ }
+ },
+ fail: function() {
+ uni.hideLoading()
+ uni.showToast({ title: '涓嬭浇澶辫触', icon: 'none' })
+ }
+ })
+ // #endif
+
+ // 闈炲井淇″皬绋嬪簭鐜锛岀洿鎺ラ瑙�
+ // #ifndef MP-WEIXIN
+ uni.previewImage({
+ urls: [imageUrl],
+ current: imageUrl
+ })
+ // #endif
+ } else {
+ this.$modal.showToast('浠呮敮鎸侀瑙堝浘鐗�')
+ }
+ },
+
+ // 鍒犻櫎闄勪欢
+ deleteAttachment(attachmentId, index) {
+ const that = this
+ this.$modal.confirm('纭畾瑕佸垹闄よ闄勪欢鍚楋紵').then(() => {
+ deleteAttachment(attachmentId).then(response => {
+ that.$modal.showToast('鍒犻櫎鎴愬姛')
+ that.attachmentList.splice(index, 1)
+ }).catch(error => {
+ console.error('鍒犻櫎闄勪欢澶辫触:', error)
+ that.$modal.showToast('鍒犻櫎澶辫触')
+ })
+ }).catch(() => {})
+ },
+
+ // 鑾峰彇鍒嗙被鍚嶇О
+ getCategoryName(category) {
+ const item = this.categoryList.find(c => c.value === category)
+ return item ? item.label : '鏈垎绫�'
+ },
+
+ // 鏍煎紡鍖栨椂闂�
+ formatTime(time) {
+ if (!time) return ''
+ return formatDateTime(time, 'YYYY-MM-DD HH:mm')
+ },
+
+ // 鏍煎紡鍖栨枃浠跺ぇ灏�
+ formatFileSize(size) {
+ if (!size) return '0B'
+ if (size < 1024) return size + 'B'
+ if (size < 1024 * 1024) return (size / 1024).toFixed(2) + 'KB'
+ return (size / 1024 / 1024).toFixed(2) + 'MB'
}
}
}
@@ -647,6 +978,18 @@
color: #333;
border-bottom: 1rpx solid #f0f0f0;
padding-bottom: 10rpx;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ .upload-btn {
+ font-size: 24rpx;
+ padding: 8rpx 20rpx;
+ background-color: #007AFF;
+ color: white;
+ border-radius: 8rpx;
+ border: none;
+ }
}
.info-item {
@@ -694,6 +1037,84 @@
background-color: #f9f9f9;
padding: 20rpx;
border-radius: 10rpx;
+ }
+
+ .no-attachment {
+ text-align: center;
+ padding: 40rpx 0;
+ color: #999;
+ font-size: 28rpx;
+ }
+
+ .attachment-item {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20rpx;
+ margin-bottom: 15rpx;
+ background-color: #f9f9f9;
+ border-radius: 10rpx;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+
+ .attachment-info {
+ flex: 1;
+ margin-right: 20rpx;
+
+ .attachment-category {
+ margin-bottom: 8rpx;
+
+ .category-tag {
+ display: inline-block;
+ padding: 4rpx 12rpx;
+ background-color: #007AFF;
+ color: white;
+ font-size: 22rpx;
+ border-radius: 4rpx;
+ }
+ }
+
+ .attachment-name {
+ font-size: 28rpx;
+ color: #333;
+ margin-bottom: 8rpx;
+ word-break: break-all;
+ }
+
+ .attachment-meta {
+ font-size: 24rpx;
+ color: #999;
+
+ .upload-time {
+ margin-right: 20rpx;
+ }
+ }
+ }
+
+ .attachment-actions {
+ display: flex;
+ flex-direction: column;
+ gap: 10rpx;
+
+ .action-btn {
+ padding: 8rpx 20rpx;
+ font-size: 24rpx;
+ border-radius: 6rpx;
+ border: none;
+
+ &.view-btn {
+ background-color: #007AFF;
+ color: white;
+ }
+
+ &.delete-btn {
+ background-color: #ff3b30;
+ color: white;
+ }
+ }
+ }
}
}
@@ -749,5 +1170,101 @@
}
}
}
+
+ .upload-dialog {
+ background-color: white;
+ border-radius: 20rpx 20rpx 0 0;
+ padding: 30rpx;
+
+ .dialog-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 30rpx;
+
+ .dialog-title {
+ font-size: 32rpx;
+ font-weight: bold;
+ color: #333;
+ }
+ }
+
+ .dialog-content {
+ .form-item {
+ margin-bottom: 30rpx;
+
+ .form-label {
+ font-size: 28rpx;
+ color: #333;
+ margin-bottom: 15rpx;
+ }
+
+ .picker-value {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20rpx;
+ background-color: #f5f5f5;
+ border-radius: 10rpx;
+ font-size: 28rpx;
+ color: #333;
+ }
+
+ .choose-image-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 30rpx;
+ background-color: #f5f5f5;
+ border-radius: 10rpx;
+ border: 2rpx dashed #ccc;
+ color: #666;
+ font-size: 28rpx;
+
+ text {
+ margin-left: 10rpx;
+ }
+ }
+ }
+
+ .preview-area {
+ margin-top: 20rpx;
+
+ .preview-image {
+ width: 100%;
+ height: 400rpx;
+ border-radius: 10rpx;
+ }
+ }
+ }
+
+ .dialog-footer {
+ display: flex;
+ gap: 20rpx;
+ margin-top: 30rpx;
+
+ button {
+ flex: 1;
+ height: 80rpx;
+ border-radius: 10rpx;
+ font-size: 30rpx;
+ border: none;
+ }
+
+ .cancel-btn {
+ background-color: #f5f5f5;
+ color: #666;
+ }
+
+ .confirm-btn {
+ background-color: #007AFF;
+ color: white;
+
+ &:disabled {
+ background-color: #ccc;
+ }
+ }
+ }
+ }
}
</style>
\ No newline at end of file
--
Gitblit v1.9.1