From 2aebbc9601ab439707f69b08e467808df9f7549c Mon Sep 17 00:00:00 2001
From: wlzboy <66905212@qq.com>
Date: 星期五, 07 十一月 2025 11:50:26 +0800
Subject: [PATCH] feat: weixin
---
app/api/task.js | 33
ruoyi-system/src/main/java/com/ruoyi/system/imagedata/WxImageUploadRequest.java | 30
ruoyi-common/src/main/java/com/ruoyi/common/config/LegacySystemConfig.java | 19
ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java | 2
ruoyi-system/src/main/java/com/ruoyi/system/domain/enums/ImageTypeEnum.java | 64
ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskAttachmentController.java | 84 +
ruoyi-common/src/main/java/com/ruoyi/common/utils/InputStreamBase64Converter.java | 35
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java | 22
ruoyi-system/src/main/java/com/ruoyi/system/imagedata/ImageDataServiceImpl.java | 644 ++++++++
sql/update_attachment_category.sql | 8
ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationController.java | 26
ruoyi-admin/src/main/java/com/ruoyi/web/controller/imagedata/ImageDataController.java | 1074 ++++++++++++++
ruoyi-system/src/main/resources/mapper/system/SysTaskAttachmentMapper.xml | 7
app/pages/task/detail.vue | 514 ++++++
ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadServiceImpl.java | 549 +++++++
ruoyi-common/src/main/java/com/ruoyi/common/config/WechatMpConfig.java | 47
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAttachment.java | 13
ruoyi-system/src/main/java/com/ruoyi/system/file/IFileUploadService.java | 108 +
ruoyi-system/src/main/resources/mapper/system/ImageDataMapper.xml | 121 +
ruoyi-common/src/main/java/com/ruoyi/common/config/WechatConfig.java | 37
ruoyi-admin/src/main/resources/application.yml | 9
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java | 140 +
/dev/null | 218 --
ruoyi-system/src/main/java/com/ruoyi/system/mapper/ImageDataMapper.java | 78 +
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java | 183 ++
ruoyi-system/src/main/java/com/ruoyi/system/domain/ImageData.java | 92 +
ruoyi-admin/src/main/java/com/ruoyi/web/controller/wechat/WechatController.java | 42
ruoyi-system/src/main/java/com/ruoyi/system/imagedata/IImageDataService.java | 200 ++
ruoyi-admin/src/main/resources/application-dev.yml | 4
ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadResponse.java | 41
30 files changed, 4,194 insertions(+), 250 deletions(-)
diff --git a/app/api/task.js b/app/api/task.js
index 9287710..f43e912 100644
--- a/app/api/task.js
+++ b/app/api/task.js
@@ -61,11 +61,14 @@
}
// 闄勪欢绠$悊API
-export function uploadAttachment(taskId, file) {
+export function uploadAttachment(taskId, file, category) {
const formData = new FormData()
formData.append('file', file)
+ if (category) {
+ formData.append('category', category)
+ }
return request({
- url: '/task/' + taskId + '/attachment',
+ url: '/task/attachment/upload/' + taskId,
method: 'post',
data: formData,
headers: {
@@ -74,6 +77,24 @@
})
}
+export function uploadAttachmentFromWechat(taskId, mediaId, category) {
+ return request({
+ url: '/task/attachment/uploadFromWechat/' + taskId,
+ method: 'post',
+ params: {
+ mediaId: mediaId,
+ category: category
+ }
+ })
+}
+
+export function getAttachmentList(taskId) {
+ return request({
+ url: '/task/attachment/list/' + taskId,
+ method: 'get'
+ })
+}
+
export function deleteAttachment(attachmentId) {
return request({
url: '/task/attachment/' + attachmentId,
@@ -81,6 +102,14 @@
})
}
+// 鑾峰彇寰俊AccessToken
+export function getWechatAccessToken() {
+ return request({
+ url: '/wechat/accessToken',
+ method: 'get'
+ })
+}
+
// 缁熻API
export function getTaskStatistics() {
return request({
diff --git a/app/pages/task/detail.vue b/app/pages/task/detail.vue
index 8598db2..58d3f7b 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,249 @@
})
}
})
+ },
+
+ // 鍔犺浇闄勪欢鍒楄〃
+ 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 => {
+ const accessToken = tokenResponse.data || tokenResponse
+ if (!accessToken) {
+ uni.hideLoading()
+ that.$modal.showToast('鑾峰彇AccessToken澶辫触')
+ return
+ }
+
+ // 绗簩姝ワ細涓婁紶鍒板井淇℃湇鍔″櫒
+ 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 +973,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 +1032,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 +1165,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
diff --git a/bin/clean.bat b/bin/clean.bat
deleted file mode 100644
index 24c0974..0000000
--- a/bin/clean.bat
+++ /dev/null
@@ -1,12 +0,0 @@
-@echo off
-echo.
-echo [信息] 清理工程target生成路径。
-echo.
-
-%~d0
-cd %~dp0
-
-cd ..
-call mvn clean
-
-pause
\ No newline at end of file
diff --git a/bin/package.bat b/bin/package.bat
deleted file mode 100644
index c693ec0..0000000
--- a/bin/package.bat
+++ /dev/null
@@ -1,12 +0,0 @@
-@echo off
-echo.
-echo [信息] 打包Web工程,生成war/jar包文件。
-echo.
-
-%~d0
-cd %~dp0
-
-cd ..
-call mvn clean package -Dmaven.test.skip=true
-
-pause
\ No newline at end of file
diff --git a/bin/run.bat b/bin/run.bat
deleted file mode 100644
index 41efbd0..0000000
--- a/bin/run.bat
+++ /dev/null
@@ -1,14 +0,0 @@
-@echo off
-echo.
-echo [信息] 使用Jar命令运行Web工程。
-echo.
-
-cd %~dp0
-cd ../ruoyi-admin/target
-
-set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
-
-java -jar %JAVA_OPTS% ruoyi-admin.jar
-
-cd bin
-pause
\ No newline at end of file
diff --git "a/doc/966120API\346\216\245\345\217\243\350\247\204\350\214\203.pdf" "b/doc/966120API\346\216\245\345\217\243\350\247\204\350\214\203.pdf"
deleted file mode 100644
index 0914adb..0000000
--- "a/doc/966120API\346\216\245\345\217\243\350\247\204\350\214\203.pdf"
+++ /dev/null
Binary files differ
diff --git "a/doc/966120\347\224\237\346\210\220\346\234\215\345\212\241\345\215\225\346\216\245\345\217\243.pdf" "b/doc/966120\347\224\237\346\210\220\346\234\215\345\212\241\345\215\225\346\216\245\345\217\243.pdf"
deleted file mode 100644
index 51381f4..0000000
--- "a/doc/966120\347\224\237\346\210\220\346\234\215\345\212\241\345\215\225\346\216\245\345\217\243.pdf"
+++ /dev/null
Binary files differ
diff --git a/doc/java8.rar b/doc/java8.rar
deleted file mode 100644
index 7cc0344..0000000
--- a/doc/java8.rar
+++ /dev/null
Binary files differ
diff --git a/doc/jdk-8u291-windows-x64.exe b/doc/jdk-8u291-windows-x64.exe
deleted file mode 100644
index da5cb5f..0000000
--- a/doc/jdk-8u291-windows-x64.exe
+++ /dev/null
Binary files differ
diff --git a/doc/sqlncli.msi b/doc/sqlncli.msi
deleted file mode 100644
index a01b934..0000000
--- a/doc/sqlncli.msi
+++ /dev/null
Binary files differ
diff --git "a/doc/\345\271\277\345\267\236\351\235\236\346\200\245\346\225\221\350\275\254\350\277\220\345\257\271\346\216\245\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\346\226\207\346\241\243\0501\051.docx" "b/doc/\345\271\277\345\267\236\351\235\236\346\200\245\346\225\221\350\275\254\350\277\220\345\257\271\346\216\245\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\346\226\207\346\241\243\0501\051.docx"
deleted file mode 100644
index 3b92eda..0000000
--- "a/doc/\345\271\277\345\267\236\351\235\236\346\200\245\346\225\221\350\275\254\350\277\220\345\257\271\346\216\245\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\346\226\207\346\241\243\0501\051.docx"
+++ /dev/null
Binary files differ
diff --git "a/doc/\345\271\277\345\267\236\351\235\236\346\200\245\346\225\221\350\275\254\350\277\220\345\257\271\346\216\245\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\346\226\207\346\241\243\0501\051.pdf" "b/doc/\345\271\277\345\267\236\351\235\236\346\200\245\346\225\221\350\275\254\350\277\220\345\257\271\346\216\245\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\346\226\207\346\241\243\0501\051.pdf"
deleted file mode 100644
index 9a06182..0000000
--- "a/doc/\345\271\277\345\267\236\351\235\236\346\200\245\346\225\221\350\275\254\350\277\220\345\257\271\346\216\245\347\254\254\344\270\211\346\226\271\346\216\245\345\217\243\346\226\207\346\241\243\0501\051.pdf"
+++ /dev/null
Binary files differ
diff --git "a/doc/\350\213\245\344\276\235\347\216\257\345\242\203\344\275\277\347\224\250\346\211\213\345\206\214.docx" "b/doc/\350\213\245\344\276\235\347\216\257\345\242\203\344\275\277\347\224\250\346\211\213\345\206\214.docx"
deleted file mode 100644
index 9e4daef..0000000
--- "a/doc/\350\213\245\344\276\235\347\216\257\345\242\203\344\275\277\347\224\250\346\211\213\345\206\214.docx"
+++ /dev/null
Binary files differ
diff --git "a/doc/\350\256\242\345\215\225\347\212\266\346\200\201\345\233\236\350\260\203\346\216\245\345\217\243\346\226\207\346\241\243.docx" "b/doc/\350\256\242\345\215\225\347\212\266\346\200\201\345\233\236\350\260\203\346\216\245\345\217\243\346\226\207\346\241\243.docx"
deleted file mode 100644
index 6e3f130..0000000
--- "a/doc/\350\256\242\345\215\225\347\212\266\346\200\201\345\233\236\350\260\203\346\216\245\345\217\243\346\226\207\346\241\243.docx"
+++ /dev/null
Binary files differ
diff --git "a/doc/\350\256\242\345\215\225\350\257\246\346\203\205.png" "b/doc/\350\256\242\345\215\225\350\257\246\346\203\205.png"
deleted file mode 100644
index 9a75e7d..0000000
--- "a/doc/\350\256\242\345\215\225\350\257\246\346\203\205.png"
+++ /dev/null
Binary files differ
diff --git "a/doc/\350\256\242\345\215\225\350\257\246\346\203\205.rp" "b/doc/\350\256\242\345\215\225\350\257\246\346\203\205.rp"
deleted file mode 100644
index 3ac2e97..0000000
--- "a/doc/\350\256\242\345\215\225\350\257\246\346\203\205.rp"
+++ /dev/null
Binary files differ
diff --git "a/docs/\344\273\273\345\212\241\347\212\266\346\200\201\345\217\230\346\233\264GPS\345\256\232\344\275\215\345\212\237\350\203\275\350\257\264\346\230\216.md" "b/docs/\344\273\273\345\212\241\347\212\266\346\200\201\345\217\230\346\233\264GPS\345\256\232\344\275\215\345\212\237\350\203\275\350\257\264\346\230\216.md"
deleted file mode 100644
index 5844142..0000000
--- "a/docs/\344\273\273\345\212\241\347\212\266\346\200\201\345\217\230\346\233\264GPS\345\256\232\344\275\215\345\212\237\350\203\275\350\257\264\346\230\216.md"
+++ /dev/null
@@ -1,282 +0,0 @@
-# 浠诲姟鐘舵�佸彉鏇碐PS瀹氫綅鍔熻兘璇存槑
-
-## 鍔熻兘姒傝堪
-
-鍦ㄦ墜鏈虹鎿嶄綔浠诲姟鐘舵�佸彉鏇存椂锛堝鍑哄彂銆佸埌杈俱�佽繑绋嬨�佸畬鎴愮瓑锛夛紝绯荤粺浼氳嚜鍔ㄨ幏鍙栧綋鍓嶇敤鎴风殑GPS浣嶇疆淇℃伅鍜屽湴鐞嗕綅缃俊鎭紝骞惰褰曞埌浠诲姟鎿嶄綔鏃ュ織涓��
-
-## 鏁版嵁搴撳彉鏇�
-
-### 1. 浠诲姟鎿嶄綔鏃ュ織琛ㄦ柊澧炲瓧娈�
-
-鍦� `sys_task_log` 琛ㄤ腑鏂板浜嗕互涓嬪瓧娈电敤浜庡瓨鍌℅PS鍜屼綅缃俊鎭細
-
-| 瀛楁鍚� | 绫诲瀷 | 璇存槑 |
-|--------|------|------|
-| latitude | DECIMAL(10,6) | 绾害 |
-| longitude | DECIMAL(10,6) | 缁忓害 |
-| location_address | VARCHAR(500) | 浣嶇疆鍦板潃锛堣閬撴垨POI鍚嶇О锛� |
-| location_province | VARCHAR(50) | 鐪佷唤 |
-| location_city | VARCHAR(50) | 鍩庡競 |
-| location_district | VARCHAR(50) | 鍖哄幙 |
-| gps_accuracy | DECIMAL(10,2) | GPS绮惧害锛堢背锛� |
-| altitude | DECIMAL(10,2) | 娴锋嫈楂樺害锛堢背锛� |
-| speed | DECIMAL(10,2) | 閫熷害锛堢背/绉掞級 |
-| heading | DECIMAL(10,2) | 鏂瑰悜瑙掑害锛�0-360搴︼級 |
-
-### 2. 鎵ц鏁版嵁搴撹剼鏈�
-
-```sql
--- 鎵ц姝よ剼鏈坊鍔燝PS浣嶇疆瀛楁
-source sql/add_location_fields.sql
-```
-
-## 鍚庣瀹炵幇
-
-### 1. 瀹炰綋绫讳慨鏀�
-
-**SysTaskLog.java** - 娣诲姞GPS浣嶇疆淇℃伅瀛楁鍙奼etter/setter鏂规硶
-
-### 2. Mapper淇敼
-
-**SysTaskLogMapper.xml** - 鏇存柊SQL璇彞锛屾敮鎸丟PS瀛楁鐨勬煡璇㈠拰鎻掑叆
-
-### 3. Service灞備慨鏀�
-
-**ISysTaskService.java** - 鏂板甯PS浣嶇疆淇℃伅鐨勭姸鎬佸彉鏇存柟娉�
-```java
-public int changeTaskStatusWithLocation(Long taskId, TaskStatus newStatus, String remark, SysTaskLog locationLog);
-```
-
-**SysTaskServiceImpl.java** - 瀹炵幇GPS浣嶇疆璁板綍閫昏緫
-- 淇濈暀鍘熸湁鐨� `changeTaskStatus` 鏂规硶锛堜笉甯PS淇℃伅锛�
-- 鏂板 `changeTaskStatusWithLocation` 鏂规硶锛堝甫GPS淇℃伅锛�
-- 淇敼 `recordTaskLog` 鏂规硶鏀寔GPS淇℃伅浼犻��
-
-### 4. Controller灞備慨鏀�
-
-**SysTaskController.java**
-- `ChangeStatusRequest` 璇锋眰瀵硅薄鏂板GPS浣嶇疆淇℃伅瀛楁
-- `changeTaskStatus` 鏂规硶鑷姩鍒ゆ柇鏄惁鍖呭惈GPS淇℃伅锛岃皟鐢ㄥ搴旂殑Service鏂规硶
-
-## 鍓嶇瀹炵幇
-
-### 1. 淇敼鐨勯〉闈�
-
-浠ヤ笅涓変釜椤甸潰鐨勪换鍔$姸鎬佸彉鏇村姛鑳藉潎宸查泦鎴怗PS瀹氫綅锛�
-
-1. **app/pages/task/detail.vue** - 浠诲姟璇︽儏椤�
-2. **app/pages/task/index.vue** - 浠诲姟鍒楄〃椤�
-3. **app/pages/index.vue** - 棣栭〉锛堣繍琛屼腑浠诲姟锛�
-
-### 2. 瀹炵幇閫昏緫
-
-#### 鑾峰彇GPS浣嶇疆淇℃伅
-
-浣跨敤UniApp鐨� `uni.getLocation` API鑾峰彇GPS淇℃伅锛�
-
-```javascript
-uni.getLocation({
- type: 'gcj02', // 浣跨敤鍥芥祴灞�鍧愭爣绯�
- geocode: true, // 瑙f瀽鍦板潃淇℃伅
- altitude: true, // 鑾峰彇楂樺害淇℃伅
- success: function(res) {
- // GPS瀹氫綅鎴愬姛锛屾惡甯︿綅缃俊鎭洿鏂扮姸鎬�
- },
- fail: function(err) {
- // GPS瀹氫綅澶辫触锛屾彁绀虹敤鎴锋槸鍚︾户缁�
- }
-})
-```
-
-#### 鑾峰彇鐨凣PS淇℃伅鍖呮嫭
-
-- **缁忕含搴�**锛歚latitude`, `longitude`
-- **鍦板潃淇℃伅**锛歚address.province`, `address.city`, `address.district`, `address.street`
-- **瀹氫綅绮惧害**锛歚accuracy`锛堢背锛�
-- **娴锋嫈楂樺害**锛歚altitude`锛堢背锛�
-- **绉诲姩閫熷害**锛歚speed`锛堢背/绉掞級
-- **绉诲姩鏂瑰悜**锛歚heading`/`direction`锛堝害锛�
-
-#### 鐘舵�佹洿鏂版祦绋�
-
-1. 鐢ㄦ埛鐐瑰嚮鐘舵�佸彉鏇存寜閽紙濡�"鍑哄彂"銆�"宸插埌杈�"绛夛級
-2. 绯荤粺寮瑰嚭浜屾纭瀵硅瘽妗�
-3. 鐢ㄦ埛纭鍚庯紝鑷姩鑾峰彇GPS浣嶇疆淇℃伅
-4. 灏嗙姸鎬佹暟鎹拰GPS淇℃伅涓�璧峰彂閫佸埌鍚庣
-5. GPS瀹氫綅澶辫触鏃讹紝鎻愮ず鐢ㄦ埛鏄惁缁х画锛堝彲閫夋嫨涓嶅甫GPS淇℃伅鏇存柊锛�
-
-### 3. 淇敼鐨勬柟娉�
-
-鎵�鏈夐〉闈㈢殑 `updateTaskStatus` 鏂规硶缁熶竴鏀逛负璋冪敤 `getLocationAndUpdateStatus` 鏂规硶锛�
-
-```javascript
-// 鏇存柊浠诲姟鐘舵��
-updateTaskStatus(taskId, status, remark) {
- this.getLocationAndUpdateStatus(taskId, status, remark)
-},
-
-// 鑾峰彇浣嶇疆淇℃伅骞舵洿鏂扮姸鎬�
-getLocationAndUpdateStatus(taskId, status, remark) {
- const that = this
-
- uni.getLocation({
- type: 'gcj02',
- geocode: true,
- altitude: true,
- success: function(res) {
- // 鎼哄甫GPS淇℃伅鏇存柊鐘舵��
- const statusData = {
- taskStatus: status,
- remark: remark,
- latitude: res.latitude,
- longitude: res.longitude,
- locationAddress: res.address ? res.address.street || res.address.poiName || '' : '',
- locationProvince: res.address ? res.address.province || '' : '',
- locationCity: res.address ? res.address.city || '' : '',
- locationDistrict: res.address ? res.address.district || '' : '',
- gpsAccuracy: res.accuracy,
- altitude: res.altitude,
- speed: res.speed,
- heading: res.direction || res.heading
- }
-
- changeTaskStatus(taskId, statusData).then(response => {
- that.$modal.showToast('鐘舵�佹洿鏂版垚鍔�')
- that.loadTaskList()
- })
- },
- fail: function(err) {
- // GPS瀹氫綅澶辫触锛屾彁绀虹敤鎴�
- that.$modal.confirm('GPS瀹氫綅澶辫触锛屾槸鍚︾户缁洿鏂扮姸鎬侊紵').then(() => {
- // 涓嶅甫GPS淇℃伅鏇存柊
- })
- }
- })
-}
-```
-
-## API鎺ュ彛
-
-### 璇锋眰绀轰緥
-
-```
-PUT /task/{taskId}/status
-Content-Type: application/json
-
-{
- "taskStatus": "DEPARTING",
- "remark": "浠诲姟宸插嚭鍙�",
- "latitude": 39.908722,
- "longitude": 116.397496,
- "locationAddress": "涓滈暱瀹夎",
- "locationProvince": "鍖椾含甯�",
- "locationCity": "鍖椾含甯�",
- "locationDistrict": "涓滃煄鍖�",
- "gpsAccuracy": 15.5,
- "altitude": 45.2,
- "speed": 0.0,
- "heading": 90.5
-}
-```
-
-### 鍝嶅簲绀轰緥
-
-```json
-{
- "code": 200,
- "msg": "鎿嶄綔鎴愬姛"
-}
-```
-
-## 鏉冮檺閰嶇疆
-
-### UniApp manifest.json閰嶇疆
-
-闇�瑕佸湪 `manifest.json` 涓坊鍔犲畾浣嶆潈闄愶細
-
-```json
-{
- "mp-weixin": {
- "permission": {
- "scope.userLocation": {
- "desc": "鎮ㄧ殑浣嶇疆淇℃伅灏嗙敤浜庤褰曚换鍔℃搷浣滀綅缃�"
- }
- }
- },
- "app-plus": {
- "distribute": {
- "android": {
- "permissions": [
- "<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
- "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
- "<uses-permission android:name=\"android.permission.ACCESS_LOCATION_EXTRA_COMMANDS\"/>"
- ]
- },
- "ios": {
- "idfa": false,
- "privacyDescription": {
- "NSLocationWhenInUseUsageDescription": "姝ゅ簲鐢ㄩ渶瑕佽幏鍙栨偍鐨勪綅缃俊鎭敤浜庤褰曚换鍔℃搷浣滀綅缃�"
- }
- }
- }
- }
-}
-```
-
-## 浣跨敤鍦烘櫙
-
-姝ゅ姛鑳介�傜敤浜庢墍鏈夐渶瑕佽褰曟搷浣滀綅缃殑浠诲姟鐘舵�佸彉鏇存搷浣滐細
-
-1. **鍑哄彂锛圖EPARTING锛�** - 璁板綍鍑哄彂鏃剁殑GPS浣嶇疆
-2. **宸插埌杈撅紙ARRIVED锛�** - 璁板綍鍒拌揪鐩殑鍦扮殑GPS浣嶇疆
-3. **杩旂▼涓紙RETURNING锛�** - 璁板綍寮�濮嬭繑绋嬫椂鐨凣PS浣嶇疆
-4. **宸插畬鎴愶紙COMPLETED锛�** - 璁板綍浠诲姟瀹屾垚鏃剁殑GPS浣嶇疆
-5. **宸插彇娑堬紙CANCELLED锛�** - 璁板綍鍙栨秷浠诲姟鏃剁殑GPS浣嶇疆
-
-## 鏁版嵁鏌ヨ
-
-### 鏌ヨ浠诲姟鎿嶄綔鏃ュ織锛堝惈GPS淇℃伅锛�
-
-```sql
-SELECT
- log_id, task_id, operation_type, operation_desc,
- operator_name, operation_time,
- latitude, longitude, location_address,
- location_province, location_city, location_district,
- gps_accuracy, altitude, speed, heading
-FROM sys_task_log
-WHERE task_id = ?
-ORDER BY operation_time DESC;
-```
-
-### 鏌ヨ鐗瑰畾鏃堕棿鑼冨洿鍐呯殑鎿嶄綔浣嶇疆
-
-```sql
-SELECT
- task_id, operation_type, operator_name, operation_time,
- latitude, longitude, location_address
-FROM sys_task_log
-WHERE operation_time BETWEEN ? AND ?
- AND latitude IS NOT NULL
- AND longitude IS NOT NULL
-ORDER BY operation_time DESC;
-```
-
-## 娉ㄦ剰浜嬮」
-
-1. **鐢ㄦ埛闅愮**锛氬湪棣栨浣跨敤瀹氫綅鍔熻兘鏃讹紝浼氳姹傜敤鎴锋巿鏉冧綅缃潈闄�
-2. **瀹氫綅澶辫触澶勭悊**锛氬鏋淕PS瀹氫綅澶辫触锛岀郴缁熶細鎻愮ず鐢ㄦ埛鏄惁缁х画鎿嶄綔锛堜笉甯PS淇℃伅锛�
-3. **缃戠粶瑕佹眰**锛氬湴鐞嗙紪鐮侊紙閫嗗湴鐞嗚В鏋愶級闇�瑕佺綉缁滆繛鎺�
-4. **鍧愭爣绯荤粺**锛氫娇鐢℅CJ-02鍧愭爣绯伙紙鍥芥祴灞�鍧愭爣绯伙級锛岄�傜敤浜庡浗鍐呭湴鍥�
-5. **绮惧害褰卞搷鍥犵礌**锛�
- - 瀹ゅ唴瀹氫綅绮惧害杈冧綆
- - 澶╂皵銆佸缓绛戠墿閬尅浼氬奖鍝嶇簿搴�
- - 绉诲姩鐘舵�佷笅绮惧害杈冮潤姝㈡椂鐣ヤ綆
-
-## 鍚庣画浼樺寲寤鸿
-
-1. **绂荤嚎瀹氫綅**锛氭敮鎸佺绾挎椂鍏堢紦瀛楪PS淇℃伅锛岃仈缃戝悗鍐嶄笂浼�
-2. **杞ㄨ抗璁板綍**锛氬彲浠ヨ褰曚换鍔℃墽琛岃繃绋嬩腑鐨勫畬鏁碐PS杞ㄨ抗
-3. **鍦板浘灞曠ず**锛氬湪浠诲姟璇︽儏椤靛睍绀烘搷浣滀綅缃殑鍦板浘鏍囪
-4. **寮傚父妫�娴�**锛氶�氳繃GPS浣嶇疆鍒ゆ柇鏄惁瀛樺湪寮傚父鎿嶄綔锛堝浣嶇疆涓嶅尮閰嶏級
-5. **缁熻鍒嗘瀽**锛氬熀浜嶨PS鏁版嵁杩涜杩愯惀鍒嗘瀽锛堝骞冲潎鍝嶅簲鏃堕棿銆佹湇鍔¤寖鍥寸瓑锛�
diff --git "a/docs/\345\234\260\347\220\206\347\274\226\347\240\201\346\234\215\345\212\241\344\275\277\347\224\250\350\257\264\346\230\216.md" "b/docs/\345\234\260\347\220\206\347\274\226\347\240\201\346\234\215\345\212\241\344\275\277\347\224\250\350\257\264\346\230\216.md"
deleted file mode 100644
index 7b0bffb..0000000
--- "a/docs/\345\234\260\347\220\206\347\274\226\347\240\201\346\234\215\345\212\241\344\275\277\347\224\250\350\257\264\346\230\216.md"
+++ /dev/null
@@ -1,218 +0,0 @@
-# 鍦扮悊缂栫爜鏈嶅姟浣跨敤璇存槑
-
-## 鍔熻兘璇存槑
-
-鍦扮悊缂栫爜鏈嶅姟鍙互灏嗗湴鍧�瀛楃涓茶浆鎹负GPS鍧愭爣锛堢粡绾害锛夛紝鐢ㄤ簬鑷姩璁$畻鍖婚櫌涔嬮棿鐨勮浆杩愯窛绂汇��
-
-## 鍚庣鎺ュ彛
-
-### 鎺ュ彛鍦板潃
-```
-GET /system/geocode/address
-```
-
-### 璇锋眰鍙傛暟
-
-| 鍙傛暟鍚� | 绫诲瀷 | 蹇呭~ | 璇存槑 |
-|--------|------|------|------|
-| address | String | 鏄� | 鍦板潃瀛楃涓诧紝渚嬪锛�"鍖椾含甯傛湞闃冲尯鏌愭煇鍖婚櫌" |
-| city | String | 鍚� | 鍩庡競鍚嶇О锛岀敤浜庢彁楂樿В鏋愬噯纭害锛屼緥濡傦細"鍖椾含甯�" |
-
-### 鍝嶅簲绀轰緥
-
-鎴愬姛鍝嶅簲锛�
-```json
-{
- "code": 200,
- "msg": "鍦扮悊缂栫爜鎴愬姛",
- "data": {
- "latitude": 39.908722,
- "longitude": 116.397496,
- "address": "鍖椾含甯備笢鍩庡尯涓滈暱瀹夎1鍙�",
- "success": true,
- "errorMessage": null
- }
-}
-```
-
-澶辫触鍝嶅簲锛�
-```json
-{
- "code": 500,
- "msg": "鍦扮悊缂栫爜澶辫触: 鍦板潃涓嶅瓨鍦�"
-}
-```
-
-## 鍓嶇浣跨敤绀轰緥
-
-### 1. 瀵煎叆API
-```javascript
-import { getCoordinatesByAddress } from '@/api/geocode'
-```
-
-### 2. 璋冪敤鎺ュ彛鑾峰彇鍧愭爣
-
-```javascript
-// 鍩烘湰鐢ㄦ硶
-async getHospitalCoordinates() {
- try {
- const res = await getCoordinatesByAddress('鍖椾含鍗忓拰鍖婚櫌')
- if (res.code === 200) {
- const { latitude, longitude } = res.data
- console.log('GPS鍧愭爣:', latitude, longitude)
- // 淇濆瓨鍧愭爣鍒拌〃鍗�
- this.taskForm.hospitalOut.latitude = latitude
- this.taskForm.hospitalOut.longitude = longitude
- }
- } catch (error) {
- console.error('鑾峰彇鍧愭爣澶辫触', error)
- }
-}
-
-// 鎸囧畾鍩庡競锛屾彁楂樺噯纭害
-async getHospitalCoordinates() {
- try {
- const res = await getCoordinatesByAddress('鍗忓拰鍖婚櫌', '鍖椾含甯�')
- if (res.code === 200) {
- const { latitude, longitude, address } = res.data
- console.log('GPS鍧愭爣:', latitude, longitude)
- console.log('鏍囧噯鍖栧湴鍧�:', address)
- }
- } catch (error) {
- console.error('鑾峰彇鍧愭爣澶辫触', error)
- }
-}
-```
-
-### 3. 鍦ㄦ�ユ晳杞繍椤甸潰涓泦鎴�
-
-鍦� `create-emergency.vue` 涓紝褰撶敤鎴烽�夋嫨鍖婚櫌鍚庤嚜鍔ㄨ幏鍙栧潗鏍囷細
-
-```javascript
-// 閫夋嫨杞嚭鍖婚櫌
-selectHospitalOut(hospital) {
- this.taskForm.hospitalOut.name = hospital.hospName
- this.taskForm.hospitalOut.address = hospital.hospAddress
- this.hospitalOutSearchKeyword = hospital.hospName
- this.showHospitalOutResults = false
- this.hospitalOutResults = []
-
- // 鑷姩鑾峰彇GPS鍧愭爣
- this.getHospitalOutCoordinates(hospital.hospAddress, hospital.hopsCity)
-},
-
-// 鑾峰彇杞嚭鍖婚櫌鍧愭爣
-async getHospitalOutCoordinates(address, city) {
- try {
- const res = await getCoordinatesByAddress(address, city)
- if (res.code === 200) {
- this.taskForm.hospitalOut.latitude = res.data.latitude
- this.taskForm.hospitalOut.longitude = res.data.longitude
- // 濡傛灉杞叆鍖婚櫌涔熷凡閫夋嫨锛岃嚜鍔ㄨ绠楄窛绂�
- if (this.taskForm.hospitalIn.latitude) {
- this.calculateDistance()
- }
- }
- } catch (error) {
- console.error('鑾峰彇杞嚭鍖婚櫌鍧愭爣澶辫触', error)
- }
-},
-
-// 鑾峰彇杞叆鍖婚櫌鍧愭爣
-async getHospitalInCoordinates(address, city) {
- try {
- const res = await getCoordinatesByAddress(address, city)
- if (res.code === 200) {
- this.taskForm.hospitalIn.latitude = res.data.latitude
- this.taskForm.hospitalIn.longitude = res.data.longitude
- // 濡傛灉杞嚭鍖婚櫌涔熷凡閫夋嫨锛岃嚜鍔ㄨ绠楄窛绂�
- if (this.taskForm.hospitalOut.latitude) {
- this.calculateDistance()
- }
- }
- } catch (error) {
- console.error('鑾峰彇杞叆鍖婚櫌鍧愭爣澶辫触', error)
- }
-},
-
-// 璁$畻涓ょ偣涔嬮棿鐨勮窛绂伙紙浣跨敤Haversine鍏紡锛�
-calculateDistance() {
- const lat1 = this.taskForm.hospitalOut.latitude
- const lon1 = this.taskForm.hospitalOut.longitude
- const lat2 = this.taskForm.hospitalIn.latitude
- const lon2 = this.taskForm.hospitalIn.longitude
-
- if (!lat1 || !lon1 || !lat2 || !lon2) {
- return
- }
-
- const R = 6371 // 鍦扮悆鍗婂緞锛堝叕閲岋級
- const dLat = (lat2 - lat1) * Math.PI / 180
- const dLon = (lon2 - lon1) * Math.PI / 180
- const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
- Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
- Math.sin(dLon / 2) * Math.sin(dLon / 2)
- const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
- const distance = R * c
-
- // 鑷姩濉厖璺濈瀛楁锛堜繚鐣�2浣嶅皬鏁帮級
- this.taskForm.transferDistance = distance.toFixed(2)
-
- uni.showToast({
- title: `棰勪及璺濈: ${distance.toFixed(2)}鍏噷`,
- icon: 'none'
- })
-}
-```
-
-## 閰嶇疆璇存槑
-
-### 鑵捐鍦板浘API瀵嗛挜閰嶇疆
-
-鍦� `application.yml` 涓厤缃吘璁湴鍥続PI瀵嗛挜锛�
-
-```yaml
-# 鑵捐鍦板浘閰嶇疆
-tencent:
- map:
- key: YOUR_TENCENT_MAP_API_KEY
-```
-
-### 鑾峰彇鑵捐鍦板浘API瀵嗛挜
-
-1. 璁块棶鑵捐浣嶇疆鏈嶅姟锛歨ttps://lbs.qq.com/
-2. 娉ㄥ唽骞剁櫥褰曞紑鍙戣�呰处鍙�
-3. 杩涘叆鎺у埗鍙帮紝鍒涘缓搴旂敤
-4. 娣诲姞Key锛岄�夋嫨WebService API
-5. 灏嗙敓鎴愮殑Key濉叆閰嶇疆鏂囦欢
-
-## 鎶�鏈疄鐜�
-
-### 鍚庣鏋舵瀯
-
-- **GeocodeResult.java**: 鍦扮悊缂栫爜缁撴灉DTO锛屽寘鍚粡绾害銆佸湴鍧�銆佹垚鍔熺姸鎬佺瓑淇℃伅
-- **IGeocodeService.java**: 鍦扮悊缂栫爜鏈嶅姟鎺ュ彛
-- **GeocodeServiceImpl.java**: 鍦扮悊缂栫爜鏈嶅姟瀹炵幇绫伙紝璋冪敤鑵捐鍦板浘WebService API
-- **GeocodeController.java**: 鍦扮悊缂栫爜鎺у埗鍣紝鎻愪緵RESTful鎺ュ彛
-
-### API璇存槑
-
-浣跨敤鑵捐鍦板浘WebService API鐨勫湴鐞嗙紪鐮佹帴鍙o細
-- API鏂囨。锛歨ttps://lbs.qq.com/service/webService/webServiceGuide/webServiceGcoder
-- 鍏嶈垂棰濋厤棰濓細10000娆�/澶�/Key
-- 璇锋眰闄愭祦锛�5娆�/绉�/Key
-
-## 娉ㄦ剰浜嬮」
-
-1. **API瀵嗛挜瀹夊叏**锛氫笉瑕佸皢API瀵嗛挜鎻愪氦鍒板叕寮�鐨勪唬鐮佷粨搴�
-2. **璋冪敤棰戠巼**锛氭敞鎰忎笉瑕佽秴杩嘇PI鐨勮皟鐢ㄩ檺鍒讹紙5娆�/绉掞級
-3. **閿欒澶勭悊**锛氶渶瑕佸鐞嗙綉缁滃紓甯搞�丄PI璋冪敤澶辫触绛夋儏鍐�
-4. **鍦板潃鍑嗙‘鎬�**锛氳緭鍏ョ殑鍦板潃瓒婅缁嗭紝瑙f瀽缁撴灉瓒婂噯纭�
-5. **鍧愭爣绯荤粺**锛氳吘璁湴鍥句娇鐢℅CJ-02鍧愭爣绯伙紙鐏槦鍧愭爣绯伙級
-
-## 鍚庣画浼樺寲寤鸿
-
-1. **缂撳瓨鏈哄埗**锛氬宸茶В鏋愯繃鐨勫湴鍧�杩涜缂撳瓨锛屽噺灏慉PI璋冪敤
-2. **鎵归噺鏌ヨ**锛氬鏋滈渶瑕佹煡璇㈠涓湴鍧�锛屽彲浠ヨ�冭檻鎵归噺鎺ュ彛
-3. **璺濈璁$畻**锛氬彲浠ョ洿鎺ヨ皟鐢ㄨ吘璁湴鍥剧殑璺嚎瑙勫垝API鑾峰彇瀹為檯瀵艰埅璺濈锛岃�屼笉鏄洿绾胯窛绂�
-4. **鍧愭爣瀛樺偍**锛氬皢瑙f瀽鍚庣殑鍧愭爣瀛樺偍鍒版暟鎹簱锛岄伩鍏嶉噸澶嶈В鏋�
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
index 32eb6f1..cd4693f 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
@@ -16,7 +16,7 @@
{
// System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(RuoYiApplication.class, args);
- System.out.println("(鈾モ棤鈥库棤)锞夛緸 鑻ヤ緷鍚姩鎴愬姛 醿�(麓凇`醿�)锞� \n" +
+ System.out.println("(鈾モ棤鈥库棤)锞夛緸 姘戣埅鍚姩鎴愬姛 醿�(麓凇`醿�)锞� \n" +
" .-------. ____ __ \n" +
" | _ _ \\ \\ \\ / / \n" +
" | ( ' ) | \\ _. / ' \n" +
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationController.java
index 2786bef..06bf884 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/evaluation/EvaluationController.java
@@ -8,13 +8,13 @@
import com.ruoyi.common.utils.WechatUtils;
import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.config.WechatMpConfig;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.system.domain.EvaluationDetail;
import com.ruoyi.system.service.IEvaluationDimensionService;
import com.ruoyi.system.domain.EvaluationDimension;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
@@ -47,6 +47,9 @@
@Autowired
private IEvaluationDimensionService evaluationDimensionService;
+
+ @Autowired
+ private WechatMpConfig wechatMpConfig;
/**
* 鏌ヨ瀹㈡埛璇勪环鍒楄〃
@@ -150,12 +153,6 @@
}
}
- @Value("${wechat.appId}")
- private String wechatAppId;
-
- @Value("${wechat.appSecret}")
- private String wechatAppSecret;
-
/**
* 鐢熸垚寰俊鎺堟潈URL
*/
@@ -170,7 +167,12 @@
logger.info("鐢熸垚寰俊鎺堟潈URL - 鍘熷redirectUri: {}", redirectUri);
// 鐢熸垚寰俊鎺堟潈URL锛屼娇鐢╯nsapi_userinfo鑾峰彇鐢ㄦ埛淇℃伅
- String authUrl = WechatUtils.generateAuthUrl(wechatAppId, redirectUri, "snsapi_userinfo", state);
+ String authUrl = WechatUtils.generateAuthUrl(
+ wechatMpConfig.getAppId(),
+ redirectUri,
+ "snsapi_userinfo",
+ state
+ );
if (authUrl == null) {
return error("鐢熸垚寰俊鎺堟潈URL澶辫触");
}
@@ -180,7 +182,7 @@
Map<String, String> result = new HashMap<>();
result.put("authUrl", authUrl);
result.put("originalRedirectUri", redirectUri);
- result.put("appId", wechatAppId);
+ result.put("appId", wechatMpConfig.getAppId());
return success(result);
} catch (Exception e) {
logger.error("鐢熸垚寰俊鎺堟潈URL澶辫触", e);
@@ -201,7 +203,11 @@
}
// 鑾峰彇缃戦〉鎺堟潈Access Token
- JSONObject tokenInfo = WechatUtils.getWebAccessToken(wechatAppId, wechatAppSecret, code);
+ JSONObject tokenInfo = WechatUtils.getWebAccessToken(
+ wechatMpConfig.getAppId(),
+ wechatMpConfig.getAppSecret(),
+ code
+ );
if (tokenInfo == null) {
return error("鑾峰彇寰俊鎺堟潈淇℃伅澶辫触");
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/imagedata/ImageDataController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/imagedata/ImageDataController.java
new file mode 100644
index 0000000..f1ca714
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/imagedata/ImageDataController.java
@@ -0,0 +1,1074 @@
+package com.ruoyi.web.controller.imagedata;
+
+import com.ruoyi.common.annotation.Anonymous;
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.config.LegacySystemConfig;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.InputStreamBase64Converter;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.file.FileUploadResponse;
+import com.ruoyi.system.file.IFileUploadService;
+import com.ruoyi.system.imagedata.IImageDataService;
+import com.ruoyi.system.domain.ImageData;
+import com.ruoyi.system.domain.enums.ImageTypeEnum;
+import com.ruoyi.system.imagedata.WxImageUploadRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.InputStream;
+import java.util.*;
+import java.util.List;
+
+/**
+ * 鍥剧墖鏁版嵁鎺у埗鍣�
+ *
+ * @author mhyl
+ * @date 2024-01-01
+ */
+@RestController
+@DataSource(DataSourceType.SQLSERVER)
+@RequestMapping("/hospital/imagedata")
+public class ImageDataController extends BaseController {
+
+ private static final Logger log = LoggerFactory.getLogger(ImageDataController.class);
+ @Autowired
+ private IImageDataService imageDataService;
+
+ @Autowired
+ private IFileUploadService fileUploadService;
+
+
+ @Autowired
+ private LegacySystemConfig legacyConfig;
+ /**
+ * 鏌ヨ鍥剧墖鏁版嵁鍒楄〃
+ */
+// @PreAuthorize("@ss.hasPermi('hospital:imagedata:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(ImageData imageData) {
+// startPage();
+ List<ImageData> list = imageDataService.selectImageDataList(imageData);
+ return getDataTable(list);
+ }
+
+ /**
+ * 瀵煎嚭鍥剧墖鏁版嵁鍒楄〃
+ */
+
+ @Log(title = "鍥剧墖鏁版嵁", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, ImageData imageData) {
+ List<ImageData> list = imageDataService.selectImageDataList(imageData);
+ ExcelUtil<ImageData> util = new ExcelUtil<ImageData>(ImageData.class);
+ util.exportExcel(response, list, "鍥剧墖鏁版嵁鏁版嵁");
+ }
+
+ /**
+ * 鑾峰彇鍥剧墖鏁版嵁璇︾粏淇℃伅
+ */
+
+ @GetMapping(value = "/{id}")
+ public AjaxResult getInfo(@PathVariable("id") Long id) {
+ return AjaxResult.success(imageDataService.selectImageDataById(id));
+ }
+
+ /**
+ * 鏂板鍥剧墖鏁版嵁
+ */
+
+ @Log(title = "鍥剧墖鏁版嵁", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@RequestBody ImageData imageData) {
+ return toAjax(imageDataService.insertImageData(imageData));
+ }
+
+ /**
+ * 淇敼鍥剧墖鏁版嵁
+ */
+ @Log(title = "鍥剧墖鏁版嵁", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@RequestBody ImageData imageData) {
+ return toAjax(imageDataService.updateImageData(imageData));
+ }
+
+ /**
+ * 鍒犻櫎鍥剧墖鏁版嵁
+ */
+ @Log(title = "鍥剧墖鏁版嵁", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public AjaxResult remove(@PathVariable Long[] ids) {
+ return toAjax(imageDataService.deleteImageDataByIds(ids));
+ }
+
+ /**
+ * 鏍规嵁璋冨害鍗旾D鏌ヨ鍥剧墖鏁版嵁
+ */
+ @GetMapping("/byDispatchOrder/{dispatchOrdID}")
+ public AjaxResult getByDispatchOrder(@PathVariable("dispatchOrdID") Long dispatchOrdID) {
+ List<ImageData> list = imageDataService.selectImageDataByDOrdIDDt(dispatchOrdID);
+ return AjaxResult.success(list);
+ }
+
+ /**
+ * 鏍规嵁璋冨害鍗旾D鍜屽浘鐗囩被鍨嬭幏鍙栨湁鏁堝浘鐗囷紙鍖呭惈瀹屾暣閾炬帴锛�
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param imageType 鍥剧墖绫诲瀷
+ * @return 鍥剧墖鏁版嵁锛堝寘鍚畬鏁撮摼鎺ワ級
+ */
+// @PreAuthorize("@ss.hasPermi('hospital:imagedata:query')")
+ @Anonymous()
+ @GetMapping("/byDispatchOrderAndType/{dispatchOrdID}/{imageType}")
+ public AjaxResult getByDispatchOrderAndType(@PathVariable("dispatchOrdID") Long dispatchOrdID,
+ @PathVariable("imageType") Integer imageType) {
+ try {
+ // 鏌ヨ鎸囧畾璋冨害鍗曞拰绫诲瀷鐨勬湁鏁堝浘鐗�
+ List<ImageData> imageDataList = imageDataService.selectImageDataByDOrdIDDtAndType(dispatchOrdID, imageType);
+
+ // 杩囨护鏈夋晥鍥剧墖锛堟湭鍒犻櫎鐨勶級
+ List<ImageData> validImages = imageDataList.stream()
+ .filter(img -> img.getImageDel() == null || img.getImageDel() == 0)
+ .collect(java.util.stream.Collectors.toList());
+
+ // 涓烘瘡涓浘鐗囨坊鍔犲畬鏁撮摼鎺�
+ for (ImageData imageData : validImages) {
+ // 娣诲姞鍘熷鍥剧墖瀹屾暣閾炬帴
+ if (StringUtils.hasText(imageData.getImageUrl())) {
+ String fullImageUrl = buildFullImageUrl(imageData.getImageUrl());
+ imageData.setImageUrl(fullImageUrl);
+ }
+
+ // 娣诲姞缂╃暐鍥惧畬鏁撮摼鎺�
+ if (StringUtils.hasText(imageData.getImageUrls())) {
+ String fullThumbnailUrl = buildFullImageUrl(imageData.getImageUrls());
+ imageData.setImageUrls(fullThumbnailUrl);
+ }
+ }
+
+ return AjaxResult.success("鑾峰彇鍥剧墖鎴愬姛", validImages);
+ } catch (Exception e) {
+ return AjaxResult.error("鑾峰彇鍥剧墖澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鏍规嵁璋冨害鍗旾D鍜屽浘鐗囩被鍨嬭幏鍙栨湁鏁堝浘鐗囷紙绠�鍖栫増锛屽彧杩斿洖鍥剧墖閾炬帴锛�
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param imageType 鍥剧墖绫诲瀷
+ * @return 鍥剧墖閾炬帴鍒楄〃
+ */
+ // @PreAuthorize("@ss.hasPermi('hospital:imagedata:query')")
+ @Anonymous()
+ @GetMapping("/links/byDispatchOrderAndType/{dispatchOrdID}/{imageType}")
+ public AjaxResult getImageLinksByDispatchOrderAndType(@PathVariable("dispatchOrdID") Long dispatchOrdID,
+ @PathVariable("imageType") Integer imageType) {
+ try {
+ // 鏌ヨ鎸囧畾璋冨害鍗曞拰绫诲瀷鐨勬湁鏁堝浘鐗�
+ List<ImageData> imageDataList = imageDataService.selectImageDataByDOrdIDDtAndType(dispatchOrdID, imageType);
+
+ // 鏋勫缓鍥剧墖閾炬帴鍒楄〃
+ List<java.util.Map<String, String>> imageLinks = new java.util.ArrayList<>();
+
+ for (ImageData imageData : imageDataList) {
+ // 鍙鐞嗘湭鍒犻櫎鐨勫浘鐗�
+ if (imageData.getImageDel() == null || imageData.getImageDel() == 0) {
+ java.util.Map<String, String> linkMap = new java.util.HashMap<>();
+
+ // 鍘熷鍥剧墖閾炬帴
+ if (StringUtils.hasText(imageData.getImageUrl())) {
+ linkMap.put("originalUrl", buildFullImageUrl(imageData.getImageUrl()));
+ }
+
+ // 缂╃暐鍥鹃摼鎺�
+ if (StringUtils.hasText(imageData.getImageUrls())) {
+ linkMap.put("thumbnailUrl", buildFullImageUrl(imageData.getImageUrls()));
+ }
+
+ // 鍥剧墖ID
+ linkMap.put("imageId", String.valueOf(imageData.getId()));
+
+ // 鍥剧墖绫诲瀷
+ linkMap.put("imageType", String.valueOf(imageData.getImageType()));
+
+ // 涓婁紶鏃堕棿
+ if (imageData.getUpImageTime() != null) {
+ linkMap.put("uploadTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, imageData.getUpImageTime()));
+ }
+
+ imageLinks.add(linkMap);
+ }
+ }
+
+ return AjaxResult.success("鑾峰彇鍥剧墖閾炬帴鎴愬姛", imageLinks);
+ } catch (Exception e) {
+ return AjaxResult.error("鑾峰彇鍥剧墖閾炬帴澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鏋勫缓瀹屾暣鐨勫浘鐗嘦RL
+ *
+ * @param imagePath 鍥剧墖璺緞
+ * @return 瀹屾暣鐨勫浘鐗嘦RL
+ */
+ private String buildFullImageUrl(String imagePath) {
+ if (!StringUtils.hasText(imagePath)) {
+ return "";
+ }
+
+ // 濡傛灉宸茬粡鏄畬鏁碪RL锛岀洿鎺ヨ繑鍥�
+ if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
+ return imagePath;
+ }
+
+ // 浠庨厤缃腑璇诲彇鏂囦欢鏈嶅姟鍣║RL
+ String fileServerUrl = legacyConfig.getFileServerUrl();
+
+ // 濡傛灉閰嶇疆涓病鏈夎缃紝浣跨敤榛樿鍊�
+ if (!StringUtils.hasText(fileServerUrl)) {
+ // 璁板綍璀﹀憡鏃ュ織
+ System.err.println("璀﹀憡锛氶厤缃枃浠朵腑鏈缃� legacy.system.fileServerUrl锛屼娇鐢ㄩ粯璁ゅ��");
+ fileServerUrl = "https://sync.966120.com.cn";
+ }
+
+ // 纭繚鏂囦欢鏈嶅姟鍣║RL涓嶄互/缁撳熬
+ if (fileServerUrl.endsWith("/")) {
+ fileServerUrl = fileServerUrl.substring(0, fileServerUrl.length() - 1);
+ }
+
+ // 澶勭悊鍥剧墖璺緞锛氱Щ闄ゅ紑澶村拰缁撳熬鐨勭┖鐧藉瓧绗�
+ imagePath = imagePath.trim();
+
+ // 绉婚櫎寮�澶村拰缁撳熬鐨勬枩鏉�
+ while (imagePath.startsWith("/")) {
+ imagePath = imagePath.substring(1);
+ }
+ while (imagePath.endsWith("/")) {
+ imagePath = imagePath.substring(0, imagePath.length() - 1);
+ }
+
+ // 澶勭悊鍙嶆枩鏉狅細灏嗗弽鏂滄潬鏇挎崲涓烘鏂滄潬
+ imagePath = imagePath.replace("\\", "/");
+
+ // 绉婚櫎璺緞涓彲鑳界殑閲嶅鏂滄潬
+ imagePath = imagePath.replaceAll("/+", "/");
+
+ // 纭繚鍥剧墖璺緞浠�/寮�澶�
+ if (!imagePath.startsWith("/")) {
+ imagePath = "/" + imagePath;
+ }
+
+ // 鏋勫缓瀹屾暣URL
+ String fullUrl = fileServerUrl + imagePath;
+
+ // 璁板綍璋冭瘯淇℃伅
+ System.out.println("鏋勫缓鍥剧墖URL - 閰嶇疆URL: " + fileServerUrl + ", 鍥剧墖璺緞: " + imagePath + ", 瀹屾暣URL: " + fullUrl);
+
+ return fullUrl;
+ }
+
+ /**
+ * 鏍规嵁鏈嶅姟鍗旾D鏌ヨ鍥剧墖鏁版嵁
+ */
+ @PreAuthorize("@ss.hasPermi('hospital:imagedata:query')")
+ @GetMapping("/byServiceOrder/{serviceOrdID}")
+ public AjaxResult getByServiceOrder(@PathVariable("serviceOrdID") Long serviceOrdID) {
+ List<ImageData> list = imageDataService.selectImageDataBySOrdIDDt(serviceOrdID);
+ return AjaxResult.success(list);
+ }
+
+ /**
+ * 鏍规嵁鍥剧墖绫诲瀷鏌ヨ鍥剧墖鏁版嵁
+ */
+ @PreAuthorize("@ss.hasPermi('hospital:imagedata:query')")
+ @GetMapping("/byType/{imageType}")
+ public AjaxResult getByType(@PathVariable("imageType") Integer imageType) {
+ List<ImageData> list = imageDataService.selectImageDataByType(imageType);
+ return AjaxResult.success(list);
+ }
+
+ /**
+ * 鏍囪鍥剧墖涓哄垹闄ょ姸鎬�
+ */
+ @PreAuthorize("@ss.hasPermi('hospital:imagedata:remove')")
+ @Log(title = "鏍囪鍥剧墖鍒犻櫎", businessType = BusinessType.DELETE)
+ @PutMapping("/markDelete/{id}")
+ public AjaxResult markDelete(@PathVariable("id") Long id) {
+ return toAjax(imageDataService.markImageDataAsDeleted(id));
+ }
+
+ /**
+ * 寰俊鍥剧墖涓婁紶澶勭悊锛堝師ASP浠g爜杞崲锛�
+ */
+ @Log(title = "寰俊鍥剧墖涓婁紶", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadWxImage")
+ public AjaxResult uploadWxImage(@RequestBody WxImageUploadRequest request) {
+
+ // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛ID
+ Integer adminId = getUserId().intValue();
+
+ String result = imageDataService.uploadWxImage(
+ request.getDispatchOrdID(),
+ request.getServiceOrdID(),
+ request.getOaid(),
+ request.getMediaId(),
+ request.getImageType(),
+ adminId
+ );
+
+ if (result.contains("鎴愬姛")) {
+ return success(result);
+ } else {
+ return error(result);
+ }
+ }
+
+ /**
+ * 寰俊鍥剧墖涓婁紶澶勭悊锛堝吋瀹瑰師鏈夊弬鏁版牸寮忥級
+ */
+ @Log(title = "寰俊鍥剧墖涓婁紶", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadWxImageForm")
+ public AjaxResult uploadWxImageForm(
+ @RequestParam(value = "DispatchOrdID", required = false) Long dispatchOrdID,
+ @RequestParam(value = "ServiceOrdID", required = false) Long serviceOrdID,
+ @RequestParam(value = "OAID", required = false) Integer oaid,
+ @RequestParam(value = "media_id", required = true) String mediaId,
+ @RequestParam(value = "ImageType", required = false) Integer imageType) {
+
+ // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛ID
+ Integer adminId = getUserId().intValue();
+
+ String result = imageDataService.uploadWxImage(dispatchOrdID, serviceOrdID, oaid, mediaId, imageType, adminId);
+
+ if (result.contains("鎴愬姛")) {
+ return success(result);
+ } else {
+ return error(result);
+ }
+ }
+
+ /**
+ * 寰俊鍥剧墖涓婁紶澶勭悊锛堝畬鏁寸増鏈紝鍖呭惈鏂囦欢涓嬭浇鍜岀缉鐣ュ浘鐢熸垚锛�
+ */
+ @Log(title = "寰俊鍥剧墖涓婁紶瀹屾暣鐗�", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadWxImageWithDownload")
+ public AjaxResult uploadWxImageWithDownload(@RequestBody WxImageUploadRequest request) {
+
+ // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛ID
+ Integer adminId = getUserId().intValue();
+
+ // 杩欓噷闇�瑕佷粠閰嶇疆鎴栬姹備腑鑾峰彇access_token
+ // 瀹為檯浣跨敤鏃跺簲璇ヤ粠寰俊閰嶇疆鎴栫紦瀛樹腑鑾峰彇
+ String accessToken = request.getAccessToken(); // 闇�瑕佸湪WxImageUploadRequest涓坊鍔犳瀛楁
+
+ if (accessToken == null || accessToken.isEmpty()) {
+ return error("缂哄皯寰俊璁块棶浠ょ墝");
+ }
+
+ String result = imageDataService.uploadWxImageWithDownload(
+ accessToken,
+ request.getMediaId(),
+ request.getDispatchOrdID(),
+ request.getOaid(),
+ request.getImageType(),
+ adminId
+ );
+
+ if (result.contains("鎴愬姛")) {
+ return success(result);
+ } else {
+ return error(result);
+ }
+ }
+
+ /**
+ * 寰俊鍥剧墖涓婁紶澶勭悊锛堝畬鏁寸増鏈紝鍏煎鍘熸湁鍙傛暟鏍煎紡锛�
+ */
+ @Log(title = "寰俊鍥剧墖涓婁紶瀹屾暣鐗�", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadWxImageWithDownloadForm")
+ public AjaxResult uploadWxImageWithDownloadForm(
+ @RequestParam(value = "access_token", required = true) String accessToken,
+ @RequestParam(value = "media_id", required = true) String mediaId,
+ @RequestParam(value = "DispatchOrdID", required = false) Long dispatchOrdID,
+ @RequestParam(value = "ServiceOrdID", required = false) Long serviceOrdID,
+ @RequestParam(value = "OAID", required = false) Integer oaid,
+ @RequestParam(value = "ImageType", required = false) Integer imageType) {
+
+ // 鑾峰彇褰撳墠鐧诲綍鐢ㄦ埛ID
+ Integer adminId = getUserId().intValue();
+
+ String result = imageDataService.uploadWxImageWithDownload(
+ accessToken, mediaId, dispatchOrdID, oaid, imageType, adminId);
+
+ if (result.contains("鎴愬姛")) {
+ return success(result);
+ } else {
+ return error(result);
+ }
+ }
+
+
+
+ /**
+ * 鐢熸垚缂╃暐鍥�
+ */
+ @Log(title = "鐢熸垚缂╃暐鍥�", businessType = BusinessType.OTHER)
+ @PostMapping("/createThumbnail")
+ public AjaxResult createThumbnail(
+ @RequestParam(value = "bigImgPath", required = true) String bigImgPath,
+ @RequestParam(value = "width", required = true) int width,
+ @RequestParam(value = "height", required = false, defaultValue = "0") int height,
+ @RequestParam(value = "smallImgPath", required = true) String smallImgPath) {
+
+ boolean result = imageDataService.createThumbnail(bigImgPath, width, height, smallImgPath);
+
+ if (result) {
+ return success("缂╃暐鍥剧敓鎴愭垚鍔�");
+ } else {
+ return error("缂╃暐鍥剧敓鎴愬け璐�");
+ }
+ }
+
+ /**
+ * 妫�鏌ユ枃浠跺吋瀹规��
+ */
+
+ @GetMapping("/checkCompatibility")
+ public AjaxResult checkFileCompatibility(@RequestParam("filePath") String filePath) {
+ try {
+ String result = imageDataService.checkFileCompatibility(filePath);
+ return AjaxResult.success("鍏煎鎬ф鏌ュ畬鎴�", result);
+ } catch (Exception e) {
+ return AjaxResult.error("鍏煎鎬ф鏌ュけ璐ワ細" + e.getMessage());
+ }
+ }
+
+ /**
+ * 楠岃瘉URL鏍煎紡鏄惁涓庢棫绯荤粺鍏煎
+ */
+ @GetMapping("/checkUrlCompatibility")
+ public AjaxResult checkUrlCompatibility(@RequestParam("url") String url) {
+ try {
+ boolean isCompatible = imageDataService.isUrlCompatible(url);
+ return AjaxResult.success("URL鍏煎鎬ф鏌ュ畬鎴�", isCompatible);
+ } catch (Exception e) {
+ return AjaxResult.error("URL鍏煎鎬ф鏌ュけ璐ワ細" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鐢熸垚涓庢棫绯荤粺鍏煎鐨勬枃浠惰矾寰�
+ */
+
+ @GetMapping("/generateCompatibleFilePath")
+ public AjaxResult generateCompatibleFilePath(@RequestParam("dispatchOrdID") Long dispatchOrdID,
+ @RequestParam("mediaId") String mediaId,
+ @RequestParam(value = "isThumbnail", defaultValue = "false") boolean isThumbnail) {
+ try {
+ String filePath = imageDataService.generateCompatibleFilePath(dispatchOrdID, mediaId, isThumbnail);
+ return AjaxResult.success("鐢熸垚鍏煎鏂囦欢璺緞鎴愬姛", filePath);
+ } catch (Exception e) {
+ return AjaxResult.error("鐢熸垚鍏煎鏂囦欢璺緞澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鐢熸垚涓庢棫绯荤粺鍏煎鐨勮闂甎RL
+ */
+
+ @GetMapping("/generateCompatibleUrl")
+ public AjaxResult generateCompatibleUrl(@RequestParam("dispatchOrdID") Long dispatchOrdID,
+ @RequestParam("mediaId") String mediaId,
+ @RequestParam(value = "isThumbnail", defaultValue = "false") boolean isThumbnail) {
+ try {
+ String url = imageDataService.generateCompatibleUrl(dispatchOrdID, mediaId, isThumbnail);
+ return AjaxResult.success("鐢熸垚鍏煎URL鎴愬姛", url);
+ } catch (Exception e) {
+ return AjaxResult.error("鐢熸垚鍏煎URL澶辫触锛�" + e.getMessage());
+ }
+ }
+
+
+ /**
+ * 閫氳繃鍥剧墖URL涓婁紶澶勭悊锛堝畬鏁寸増鏈級
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param serviceOrdID 鏈嶅姟鍗旾D
+ * @param oaid OA鐢ㄦ埛ID
+ * @param imageUrl 鍥剧墖URL
+ * @param thumbnailUrl 缂╃暐鍥綰RL
+ * @param imageType 鍥剧墖绫诲瀷
+ * @return 澶勭悊缁撴灉
+ */
+ @PreAuthorize("@ss.hasPermi('hospital:imagedata:add')")
+ @Log(title = "鍥剧墖URL涓婁紶", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadByUrl")
+ public AjaxResult uploadImageByUrl(@RequestParam(value = "dispatchOrdID", required = false) Long dispatchOrdID,
+ @RequestParam(value = "serviceOrdID", required = false) Long serviceOrdID,
+ @RequestParam(value = "oaid", required = false) Integer oaid,
+ @RequestParam("imageUrl") String imageUrl,
+ @RequestParam(value = "thumbnailUrl", required = false) String thumbnailUrl,
+ @RequestParam(value = "imageType", defaultValue = "0") Integer imageType) {
+ try {
+ // 鑾峰彇褰撳墠绠$悊鍛業D
+ Integer adminId = getUserId().intValue();
+
+ // 璋冪敤鍥剧墖鏁版嵁鏈嶅姟澶勭悊涓婁紶
+ String result = imageDataService.uploadImageByUrl(dispatchOrdID, serviceOrdID, oaid,
+ imageUrl, thumbnailUrl, imageType, adminId);
+
+ if (result.contains("鎴愬姛")) {
+ return AjaxResult.success("鍥剧墖URL涓婁紶鎴愬姛", result);
+ } else {
+ return AjaxResult.error(result);
+ }
+ } catch (Exception e) {
+ return AjaxResult.error("鍥剧墖URL涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 閫氳繃鍥剧墖URL涓婁紶澶勭悊锛堢畝鍖栫増鏈級
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param serviceOrdID 鏈嶅姟鍗旾D
+ * @param oaid OA鐢ㄦ埛ID
+ * @param imageUrl 鍥剧墖URL
+ * @param imageType 鍥剧墖绫诲瀷
+ * @return 澶勭悊缁撴灉
+ */
+ @Log(title = "鍥剧墖URL涓婁紶绠�鍖栫増", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadByUrlSimple")
+ public AjaxResult uploadImageByUrlSimple(@RequestParam(value = "dispatchOrdID", required = false) Long dispatchOrdID,
+ @RequestParam(value = "serviceOrdID", required = false) Long serviceOrdID,
+ @RequestParam(value = "oaid", required = false) Integer oaid,
+ @RequestParam("imageUrl") String imageUrl,
+ @RequestParam(value = "imageType", defaultValue = "0") Integer imageType) {
+ try {
+ // 鑾峰彇褰撳墠绠$悊鍛業D
+ Integer adminId = getUserId().intValue();
+
+ // 璋冪敤鍥剧墖鏁版嵁鏈嶅姟澶勭悊涓婁紶锛堢畝鍖栫増锛�
+ String result = imageDataService.uploadImageByUrlSimple(dispatchOrdID, serviceOrdID, oaid,
+ imageUrl, imageType, adminId);
+
+ if (result.contains("鎴愬姛")) {
+ return AjaxResult.success("鍥剧墖URL涓婁紶鎴愬姛", result);
+ } else {
+ return AjaxResult.error(result);
+ }
+ } catch (Exception e) {
+ return AjaxResult.error("鍥剧墖URL涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 閫氳繃鍥剧墖URL涓婁紶澶勭悊锛圝SON鏍煎紡锛�
+ *
+ * @param requestBody 璇锋眰浣�
+ * @return 澶勭悊缁撴灉
+ */
+ @PreAuthorize("@ss.hasPermi('hospital:imagedata:add')")
+ @Log(title = "鍥剧墖URL涓婁紶JSON", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadByUrlJson")
+ public AjaxResult uploadImageByUrlJson(@RequestBody ImageUrlUploadRequest requestBody) {
+ try {
+ // 鑾峰彇褰撳墠绠$悊鍛業D
+ Integer adminId = getUserId().intValue();
+
+ // 璋冪敤鍥剧墖鏁版嵁鏈嶅姟澶勭悊涓婁紶
+ String result = imageDataService.uploadImageByUrl(requestBody.getDispatchOrdID(),
+ requestBody.getServiceOrdID(), requestBody.getOaid(), requestBody.getImageUrl(),
+ requestBody.getThumbnailUrl(), requestBody.getImageType(), adminId);
+
+ if (result.contains("鎴愬姛")) {
+ return AjaxResult.success("鍥剧墖URL涓婁紶鎴愬姛", result);
+ } else {
+ return AjaxResult.error(result);
+ }
+ } catch (Exception e) {
+ return AjaxResult.error("鍥剧墖URL涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鍥剧墖URL涓婁紶璇锋眰瀵硅薄
+ */
+ public static class ImageUrlUploadRequest {
+
+ private Long dispatchOrdID;
+ private Long serviceOrdID;
+ private Integer oaid;
+ private String imageUrl;
+ private String thumbnailUrl;
+ private Integer imageType;
+
+ // getter鍜宻etter鏂规硶
+ public Long getDispatchOrdID() {
+ return dispatchOrdID;
+ }
+
+ public void setDispatchOrdID(Long dispatchOrdID) {
+ this.dispatchOrdID = dispatchOrdID;
+ }
+
+ public Long getServiceOrdID() {
+ return serviceOrdID;
+ }
+
+ public void setServiceOrdID(Long serviceOrdID) {
+ this.serviceOrdID = serviceOrdID;
+ }
+
+ public Integer getOaid() {
+ return oaid;
+ }
+
+ public void setOaid(Integer oaid) {
+ this.oaid = oaid;
+ }
+
+ public String getImageUrl() {
+ return imageUrl;
+ }
+
+ public void setImageUrl(String imageUrl) {
+ this.imageUrl = imageUrl;
+ }
+
+ public String getThumbnailUrl() {
+ return thumbnailUrl;
+ }
+
+ public void setThumbnailUrl(String thumbnailUrl) {
+ this.thumbnailUrl = thumbnailUrl;
+ }
+
+ public Integer getImageType() {
+ return imageType;
+ }
+
+ public void setImageType(Integer imageType) {
+ this.imageType = imageType;
+ }
+ }
+
+ /**
+ * 鍥剧墖鏂囦欢涓婁紶鎺ュ彛
+ *
+ * @param file 涓婁紶鐨勫浘鐗囨枃浠�
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param serviceOrdID 鏈嶅姟鍗旾D
+ * @param imageType 鍥剧墖绫诲瀷
+ * @return 澶勭悊缁撴灉
+ */
+// @PreAuthorize("@ss.hasPermi('hospital:imagedata:add')")
+ @Anonymous()
+ @Log(title = "鍥剧墖鏂囦欢涓婁紶", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadFile")
+ public AjaxResult uploadImageFile(@RequestParam("file") MultipartFile file,
+ @RequestParam(value = "dispatchOrdID", required = false) Long dispatchOrdID,
+ @RequestParam(value = "serviceOrdID", required = false) Long serviceOrdID,
+ @RequestParam(value = "imageType", defaultValue = "0", required = true) Integer imageType,
+ @RequestParam(value = "adminId", defaultValue = "0", required = false) Integer adminId) {
+ try {
+
+ adminId = getUserId().intValue();
+
+ // 楠岃瘉鏂囦欢
+ if (file.isEmpty()) {
+ return AjaxResult.error("璇烽�夋嫨瑕佷笂浼犵殑鍥剧墖鏂囦欢");
+ }
+
+ // 楠岃瘉鏂囦欢绫诲瀷
+ String originalFilename = file.getOriginalFilename();
+ if (originalFilename == null || !isValidImageFile(originalFilename)) {
+ return AjaxResult.error("鍙敮鎸佷笂浼犲浘鐗囨枃浠讹紙jpg銆乯peg銆乸ng銆乬if銆乥mp锛�");
+ }
+
+ // 鐢熸垚鐩爣璺緞锛堜娇鐢ㄥ勾鏈堢洰褰曠粨鏋勶級
+ String yearMonth = DateUtils.datePath();
+ String targetPath = dispatchOrdID.toString();
+ //鍦ㄧ粨鏋滃彟杩斿洖 fileUrl,thumbnailUrl,鍙妋ediaid
+ // 浣跨敤鏂囦欢涓婁紶鏈嶅姟淇濆瓨鍒版枃浠舵湇鍔″櫒锛堝寘鍚缉鐣ュ浘鐢熸垚锛�
+ FileUploadResponse uploadResponse = fileUploadService.uploadMultipartFileWithThumbnail(file, targetPath);
+
+ // 娣诲姞璋冭瘯淇℃伅
+ System.out.println("鏂囦欢涓婁紶鍝嶅簲 - 鎴愬姛: " + uploadResponse.isSuccess());
+ System.out.println("鏂囦欢涓婁紶鍝嶅簲 - 娑堟伅: " + uploadResponse.getMessage());
+ System.out.println("鏂囦欢涓婁紶鍝嶅簲 - 鏂囦欢璺緞: " + uploadResponse.getFilePath());
+ System.out.println("鏂囦欢涓婁紶鍝嶅簲 - 缂╃暐鍥捐矾寰�: " + uploadResponse.getThumbnailPath());
+
+ if (!uploadResponse.isSuccess()) {
+ return AjaxResult.error("鏂囦欢涓婁紶澶辫触锛�" + uploadResponse.getMessage());
+ }
+
+ // 鍒涘缓鍥剧墖鏁版嵁瀵硅薄
+ ImageData imageData = new ImageData();
+ imageData.setDOrdIDDt(dispatchOrdID);
+ imageData.setSOrdIDDt(serviceOrdID);
+ imageData.setImageType(imageType);
+ imageData.setImageUrl(uploadResponse.getFilePath());
+ imageData.setImageUrls(uploadResponse.getThumbnailPath()); // 缂╃暐鍥捐矾寰�
+ imageData.setUpImageTime(new Date());
+ imageData.setUpImageOAid(adminId);
+ imageData.setImageDel(0);
+
+ // 鎻掑叆鏁版嵁搴�
+ int result = imageDataService.insertImageData(imageData);
+
+ if (result > 0) {
+ // 鏍规嵁鍥剧墖绫诲瀷杩涜鐗规畩澶勭悊
+ ImageTypeEnum imageTypeEnum = ImageTypeEnum.getByCode(imageType);
+
+
+ //杩斿洖鍏ㄨ矾寰�
+ //鍦ㄧ粨鏋滃彟杩斿洖 fileUrl,thumbnailUrl,鍙奿d
+ HashMap<String, String> map = new HashMap<>();
+ //鍔犱笂fileServerUrl
+ map.put("fileUrl", buildFullImageUrl(uploadResponse.getFilePath()));
+ map.put("thumbnailUrl", buildFullImageUrl(uploadResponse.getThumbnailPath()));
+ map.put("id", imageData.getId().toString());
+
+ return AjaxResult.success("鍥剧墖涓婁紶鎴愬姛", map);
+ } else {
+ return AjaxResult.error("鍥剧墖鏁版嵁淇濆瓨澶辫触");
+ }
+
+ } catch (Exception e) {
+ return AjaxResult.error("鍥剧墖涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+ @Anonymous()
+ @Log(title = "鍥剧墖鏂囦欢涓婁紶", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadFileBase64")
+ public AjaxResult uploadFileBase64(@RequestParam("fileContent") String fileContent,@RequestParam("filename") String filename,
+ @RequestParam(value = "dispatchOrdID", required = false) Long dispatchOrdID,
+ @RequestParam(value = "serviceOrdID", required = false) Long serviceOrdID,
+ @RequestParam(value = "imageType", defaultValue = "0", required = true) Integer imageType,
+ @RequestParam(value = "adminId", defaultValue = "0", required = false) Integer adminId) {
+ try {
+
+ if( adminId == 0)
+ adminId = getUserId().intValue();
+
+ InputStream stream= InputStreamBase64Converter.base64ToInputStream(fileContent);
+
+ // 鐢熸垚鐩爣璺緞锛堜娇鐢ㄥ勾鏈堢洰褰曠粨鏋勶級
+ String yearMonth = DateUtils.datePath();
+ String targetPath = dispatchOrdID.toString();
+ //鍦ㄧ粨鏋滃彟杩斿洖 fileUrl,thumbnailUrl,鍙妋ediaid
+ // 浣跨敤鏂囦欢涓婁紶鏈嶅姟淇濆瓨鍒版枃浠舵湇鍔″櫒锛堝寘鍚缉鐣ュ浘鐢熸垚锛�
+ FileUploadResponse uploadResponse = fileUploadService.uploadInputStream(stream,filename, targetPath);
+
+ // 娣诲姞璋冭瘯淇℃伅
+ System.out.println("鏂囦欢涓婁紶鍝嶅簲 - 鎴愬姛: " + uploadResponse.isSuccess());
+ System.out.println("鏂囦欢涓婁紶鍝嶅簲 - 娑堟伅: " + uploadResponse.getMessage());
+ System.out.println("鏂囦欢涓婁紶鍝嶅簲 - 鏂囦欢璺緞: " + uploadResponse.getFilePath());
+ System.out.println("鏂囦欢涓婁紶鍝嶅簲 - 缂╃暐鍥捐矾寰�: " + uploadResponse.getThumbnailPath());
+
+ if (!uploadResponse.isSuccess()) {
+ return AjaxResult.error("鏂囦欢涓婁紶澶辫触锛�" + uploadResponse.getMessage());
+ }
+
+ // 鍒涘缓鍥剧墖鏁版嵁瀵硅薄
+ ImageData imageData = new ImageData();
+ imageData.setDOrdIDDt(dispatchOrdID);
+ imageData.setSOrdIDDt(serviceOrdID);
+ imageData.setImageType(imageType);
+ imageData.setImageUrl(uploadResponse.getFilePath());
+ imageData.setImageUrls(uploadResponse.getThumbnailPath()); // 缂╃暐鍥捐矾寰�
+ imageData.setUpImageTime(new Date());
+ imageData.setUpImageOAid(adminId);
+ imageData.setImageDel(0);
+
+ // 鎻掑叆鏁版嵁搴�
+ int result = imageDataService.insertImageData(imageData);
+
+ if (result > 0) {
+ // 鏍规嵁鍥剧墖绫诲瀷杩涜鐗规畩澶勭悊
+ ImageTypeEnum imageTypeEnum = ImageTypeEnum.getByCode(imageType);
+
+
+ //杩斿洖鍏ㄨ矾寰�
+ //鍦ㄧ粨鏋滃彟杩斿洖 fileUrl,thumbnailUrl,鍙奿d
+ HashMap<String, String> map = new HashMap<>();
+ //鍔犱笂fileServerUrl
+ map.put("fileUrl", buildFullImageUrl(uploadResponse.getFilePath()));
+ map.put("thumbnailUrl", buildFullImageUrl(uploadResponse.getThumbnailPath()));
+ map.put("id", imageData.getId().toString());
+
+ return AjaxResult.success("鍥剧墖涓婁紶鎴愬姛", map);
+ } else {
+ return AjaxResult.error("鍥剧墖鏁版嵁淇濆瓨澶辫触");
+ }
+
+ } catch (Exception e) {
+ return AjaxResult.error("鍥剧墖涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 寰俊灏忕▼搴忎笓鐢ㄥ浘鐗囨枃浠朵笂浼犳帴鍙�
+ * 鏀寔寰俊灏忕▼搴忕殑 wx.uploadFile API
+ *
+ * @param request HttpServletRequest 璇锋眰瀵硅薄
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param serviceOrdID 鏈嶅姟鍗旾D
+ * @param imageType 鍥剧墖绫诲瀷
+ * @param adminId 绠$悊鍛業D
+ * @return 澶勭悊缁撴灉
+ */
+ @Anonymous()
+ @Log(title = "寰俊灏忕▼搴忓浘鐗囦笂浼�", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadWxFile")
+ public AjaxResult uploadWxFile(HttpServletRequest request,
+ @RequestParam(value = "dispatchOrdID", required = false) Long dispatchOrdID,
+ @RequestParam(value = "serviceOrdID", required = false) Long serviceOrdID,
+ @RequestParam(value = "imageType", defaultValue = "0", required = true) Integer imageType,
+ @RequestParam(value = "adminId", defaultValue = "0", required = false) Integer adminId) {
+ try {
+ adminId = getUserId().intValue();
+
+ // 鑾峰彇鏂囦欢鍙傛暟 - 寰俊灏忕▼搴忎笓鐢�
+ MultipartFile file = null;
+
+ // 妫�鏌ユ槸鍚︿负 multipart 璇锋眰
+ if (request instanceof MultipartHttpServletRequest) {
+ MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
+
+ // 寰俊灏忕▼搴忛�氬父浣跨敤 "file" 浣滀负鏂囦欢鍙傛暟鍚�
+ file = multipartRequest.getFile("file");
+
+ // 濡傛灉娌℃壘鍒帮紝灏濊瘯鍏朵粬鍙兘鐨勫弬鏁板悕
+ if (file == null || file.isEmpty()) {
+ String[] possibleFileParams = {"image", "photo", "upload"};
+ for (String paramName : possibleFileParams) {
+ file = multipartRequest.getFile(paramName);
+ if (file != null && !file.isEmpty()) {
+ break;
+ }
+ }
+ }
+
+ // 濡傛灉杩樻槸娌℃壘鍒版枃浠讹紝鑾峰彇绗竴涓枃浠�
+ if (file == null || file.isEmpty()) {
+ Iterator<String> fileNames = multipartRequest.getFileNames();
+ if (fileNames.hasNext()) {
+ file = multipartRequest.getFile(fileNames.next());
+ }
+ }
+ }
+
+ // 楠岃瘉鏂囦欢
+ if (file == null || file.isEmpty()) {
+ return AjaxResult.error("璇烽�夋嫨瑕佷笂浼犵殑鍥剧墖鏂囦欢");
+ }
+
+ // 楠岃瘉鏂囦欢绫诲瀷
+ String originalFilename = file.getOriginalFilename();
+ if (originalFilename == null || !isValidImageFile(originalFilename)) {
+ return AjaxResult.error("鍙敮鎸佷笂浼犲浘鐗囨枃浠讹紙jpg銆乯peg銆乸ng銆乬if銆乥mp锛�");
+ }
+
+ // 鐢熸垚鐩爣璺緞
+ String targetPath = dispatchOrdID != null ? dispatchOrdID.toString() : "default";
+
+ // 浣跨敤鏂囦欢涓婁紶鏈嶅姟淇濆瓨鍒版枃浠舵湇鍔″櫒锛堝寘鍚缉鐣ュ浘鐢熸垚锛�
+ FileUploadResponse uploadResponse = fileUploadService.uploadMultipartFileWithThumbnail(file, targetPath);
+
+ // 娣诲姞璋冭瘯淇℃伅
+ System.out.println("寰俊灏忕▼搴忔枃浠朵笂浼犲搷搴� - 鎴愬姛: " + uploadResponse.isSuccess());
+ System.out.println("寰俊灏忕▼搴忔枃浠朵笂浼犲搷搴� - 娑堟伅: " + uploadResponse.getMessage());
+ System.out.println("寰俊灏忕▼搴忔枃浠朵笂浼犲搷搴� - 鏂囦欢璺緞: " + uploadResponse.getFilePath());
+ System.out.println("寰俊灏忕▼搴忔枃浠朵笂浼犲搷搴� - 缂╃暐鍥捐矾寰�: " + uploadResponse.getThumbnailPath());
+
+ if (!uploadResponse.isSuccess()) {
+ return AjaxResult.error("鏂囦欢涓婁紶澶辫触锛�" + uploadResponse.getMessage());
+ }
+
+ // 鍒涘缓鍥剧墖鏁版嵁瀵硅薄
+ ImageData imageData = new ImageData();
+ imageData.setDOrdIDDt(dispatchOrdID);
+ imageData.setSOrdIDDt(serviceOrdID);
+ imageData.setImageType(imageType);
+ imageData.setImageUrl(uploadResponse.getFilePath());
+ imageData.setImageUrls(uploadResponse.getThumbnailPath()); // 缂╃暐鍥捐矾寰�
+ imageData.setUpImageTime(new Date());
+ imageData.setUpImageOAid(adminId);
+ imageData.setImageDel(0);
+
+ // 鎻掑叆鏁版嵁搴�
+ int result = imageDataService.insertImageData(imageData);
+
+ if (result > 0) {
+ // 鏍规嵁鍥剧墖绫诲瀷杩涜鐗规畩澶勭悊
+ ImageTypeEnum imageTypeEnum = ImageTypeEnum.getByCode(imageType);
+
+
+
+ // 杩斿洖寰俊灏忕▼搴忛渶瑕佺殑鏍煎紡
+ HashMap<String, Object> map = new HashMap<>();
+ map.put("fileUrl", buildFullImageUrl(uploadResponse.getFilePath()));
+ map.put("thumbnailUrl", buildFullImageUrl(uploadResponse.getThumbnailPath()));
+ map.put("id", imageData.getId());
+ map.put("success", true);
+ map.put("message", "鍥剧墖涓婁紶鎴愬姛");
+
+ return AjaxResult.success("鍥剧墖涓婁紶鎴愬姛", map);
+ } else {
+ return AjaxResult.error("鍥剧墖鏁版嵁淇濆瓨澶辫触");
+ }
+
+ } catch (Exception e) {
+ log.error("寰俊灏忕▼搴忓浘鐗囦笂浼犲け璐�", e);
+ return AjaxResult.error("鍥剧墖涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 寰俊灏忕▼搴廈ase64鍥剧墖涓婁紶鎺ュ彛
+ * 鏀寔寰俊灏忕▼搴忓皢鍥剧墖杞崲涓築ase64鍚庝笂浼�
+ *
+ * @param fileContent Base64缂栫爜鐨勫浘鐗囧唴瀹�
+ * @param filename 鏂囦欢鍚�
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param serviceOrdID 鏈嶅姟鍗旾D
+ * @param imageType 鍥剧墖绫诲瀷
+ * @param adminId 绠$悊鍛業D
+ * @return 澶勭悊缁撴灉
+ */
+ @Anonymous()
+ @Log(title = "寰俊灏忕▼搴廈ase64鍥剧墖涓婁紶", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadWxBase64")
+ public AjaxResult uploadWxBase64(@RequestParam("fileContent") String fileContent,
+ @RequestParam("filename") String filename,
+ @RequestParam(value = "dispatchOrdID", required = false) Long dispatchOrdID,
+ @RequestParam(value = "serviceOrdID", required = false) Long serviceOrdID,
+ @RequestParam(value = "imageType", defaultValue = "0", required = true) Integer imageType,
+ @RequestParam(value = "adminId", defaultValue = "0", required = false) Integer adminId) {
+ try {
+ if (adminId == 0) {
+ adminId = getUserId().intValue();
+ }
+
+ // 楠岃瘉Base64鍐呭
+ if (fileContent == null || fileContent.trim().isEmpty()) {
+ return AjaxResult.error("鍥剧墖鍐呭涓嶈兘涓虹┖");
+ }
+
+ // 楠岃瘉鏂囦欢绫诲瀷
+ if (filename == null || !isValidImageFile(filename)) {
+ return AjaxResult.error("鍙敮鎸佷笂浼犲浘鐗囨枃浠讹紙jpg銆乯peg銆乸ng銆乬if銆乥mp锛�");
+ }
+
+ // 灏咮ase64杞崲涓篒nputStream
+ InputStream stream = InputStreamBase64Converter.base64ToInputStream(fileContent);
+
+ // 鐢熸垚鐩爣璺緞
+ String targetPath = dispatchOrdID != null ? dispatchOrdID.toString() : "default";
+
+ // 浣跨敤鏂囦欢涓婁紶鏈嶅姟淇濆瓨鍒版枃浠舵湇鍔″櫒
+ FileUploadResponse uploadResponse = fileUploadService.uploadInputStream(stream, filename, targetPath);
+
+ // 娣诲姞璋冭瘯淇℃伅
+ System.out.println("寰俊灏忕▼搴廈ase64涓婁紶鍝嶅簲 - 鎴愬姛: " + uploadResponse.isSuccess());
+ System.out.println("寰俊灏忕▼搴廈ase64涓婁紶鍝嶅簲 - 娑堟伅: " + uploadResponse.getMessage());
+ System.out.println("寰俊灏忕▼搴廈ase64涓婁紶鍝嶅簲 - 鏂囦欢璺緞: " + uploadResponse.getFilePath());
+ System.out.println("寰俊灏忕▼搴廈ase64涓婁紶鍝嶅簲 - 缂╃暐鍥捐矾寰�: " + uploadResponse.getThumbnailPath());
+
+ if (!uploadResponse.isSuccess()) {
+ return AjaxResult.error("鏂囦欢涓婁紶澶辫触锛�" + uploadResponse.getMessage());
+ }
+
+ // 鍒涘缓鍥剧墖鏁版嵁瀵硅薄
+ ImageData imageData = new ImageData();
+ imageData.setDOrdIDDt(dispatchOrdID);
+ imageData.setSOrdIDDt(serviceOrdID);
+ imageData.setImageType(imageType);
+ imageData.setImageUrl(uploadResponse.getFilePath());
+ imageData.setImageUrls(uploadResponse.getThumbnailPath()); // 缂╃暐鍥捐矾寰�
+ imageData.setUpImageTime(new Date());
+ imageData.setUpImageOAid(adminId);
+ imageData.setImageDel(0);
+
+ // 鎻掑叆鏁版嵁搴�
+ int result = imageDataService.insertImageData(imageData);
+
+ if (result > 0) {
+ // 鏍规嵁鍥剧墖绫诲瀷杩涜鐗规畩澶勭悊
+ ImageTypeEnum imageTypeEnum = ImageTypeEnum.getByCode(imageType);
+
+
+
+ // 杩斿洖寰俊灏忕▼搴忛渶瑕佺殑鏍煎紡
+ HashMap<String, Object> map = new HashMap<>();
+ map.put("fileUrl", buildFullImageUrl(uploadResponse.getFilePath()));
+ map.put("thumbnailUrl", buildFullImageUrl(uploadResponse.getThumbnailPath()));
+ map.put("id", imageData.getId());
+ map.put("success", true);
+ map.put("message", "鍥剧墖涓婁紶鎴愬姛");
+
+ return AjaxResult.success("鍥剧墖涓婁紶鎴愬姛", map);
+ } else {
+ return AjaxResult.error("鍥剧墖鏁版嵁淇濆瓨澶辫触");
+ }
+
+ } catch (Exception e) {
+ log.error("寰俊灏忕▼搴廈ase64鍥剧墖涓婁紶澶辫触", e);
+ return AjaxResult.error("鍥剧墖涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 楠岃瘉鏄惁涓烘湁鏁堢殑鍥剧墖鏂囦欢
+ */
+ private boolean isValidImageFile(String filename) {
+ String[] allowedExtensions = {".jpg", ".jpeg", ".png", ".gif", ".bmp"};
+ String lowerFilename = filename.toLowerCase();
+ for (String ext : allowedExtensions) {
+ if (lowerFilename.endsWith(ext)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 鑾峰彇鏂囦欢鎵╁睍鍚�
+ */
+ private String getFileExtension(String filename) {
+ int lastDotIndex = filename.lastIndexOf('.');
+ if (lastDotIndex > 0) {
+ return filename.substring(lastDotIndex + 1);
+ }
+ return "jpg"; // 榛樿鎵╁睍鍚�
+ }
+
+ /**
+ * 鑾峰彇涓婁紶璺緞
+ */
+ private String getUploadPath() {
+ // 杩欓噷鍙互鏍规嵁瀹為檯閰嶇疆杩斿洖涓婁紶璺緞
+ // 鍙互浠庨厤缃枃浠朵腑璇诲彇鎴栦娇鐢ㄩ粯璁よ矾寰�
+ return System.getProperty("user.dir") + "/upload";
+ }
+
+
+
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskAttachmentController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskAttachmentController.java
index b12fa9e..d9e5490 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskAttachmentController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/task/SysTaskAttachmentController.java
@@ -1,8 +1,13 @@
package com.ruoyi.web.controller.task;
import java.util.List;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.OutputStream;
import javax.servlet.http.HttpServletResponse;
+import com.ruoyi.common.utils.WechatUtils;
+import com.ruoyi.common.config.WechatConfig;
import com.ruoyi.system.domain.SysTask;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
@@ -33,6 +38,9 @@
@Autowired
private ISysTaskService sysTaskService;
+
+ @Autowired
+ private WechatConfig wechatConfig;
/**
* 鏌ヨ浠诲姟闄勪欢鍒楄〃
@@ -50,9 +58,11 @@
@PreAuthorize("@ss.hasPermi('task:general:edit')")
@Log(title = "浠诲姟闄勪欢", businessType = BusinessType.INSERT)
@PostMapping("/upload/{taskId}")
- public AjaxResult upload(@PathVariable("taskId") Long taskId, @RequestParam("file") MultipartFile file) {
+ public AjaxResult upload(@PathVariable("taskId") Long taskId,
+ @RequestParam("file") MultipartFile file,
+ @RequestParam(value = "category", required = false) String category) {
try {
- int result = sysTaskService.uploadAttachment(taskId, file);
+ int result = sysTaskService.uploadAttachment(taskId, file, category);
if (result > 0) {
return success("涓婁紶鎴愬姛");
} else {
@@ -81,4 +91,74 @@
return error("鍒犻櫎澶辫触锛�" + e.getMessage());
}
}
+
+ /**
+ * 浠庡井淇ediaId涓婁紶闄勪欢锛堝井淇″皬绋嬪簭涓撶敤锛�
+ */
+ @PreAuthorize("@ss.hasPermi('task:general:edit')")
+ @Log(title = "浠诲姟闄勪欢", businessType = BusinessType.INSERT)
+ @PostMapping("/uploadFromWechat/{taskId}")
+ public AjaxResult uploadFromWechat(@PathVariable("taskId") Long taskId,
+ @RequestParam("mediaId") String mediaId,
+ @RequestParam(value = "category", required = false) String category) {
+ try {
+ // 鑾峰彇寰俊AccessToken
+ String accessToken = WechatUtils.getAccessToken(
+ wechatConfig.getAppId(),
+ wechatConfig.getAppSecret()
+ );
+ if (accessToken == null || accessToken.isEmpty()) {
+ return error("鑾峰彇寰俊AccessToken澶辫触");
+ }
+
+ // 閫氳繃mediaId涓婁紶闄勪欢
+ int result = sysTaskService.uploadAttachmentFromWechat(taskId, accessToken, mediaId, category);
+ if (result > 0) {
+ return success("涓婁紶鎴愬姛");
+ } else {
+ return error("涓婁紶澶辫触");
+ }
+ } catch (Exception e) {
+ return error("涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 涓嬭浇闄勪欢
+ */
+ @GetMapping("/download/{attachmentId}")
+ public void downloadAttachment(@PathVariable("attachmentId") Long attachmentId, HttpServletResponse response) {
+ try {
+ SysTaskAttachment attachment = sysTaskService.getAttachmentById(attachmentId);
+ if (attachment == null) {
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+ return;
+ }
+
+ File file = new File(attachment.getFilePath());
+ if (!file.exists()) {
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+ return;
+ }
+
+ // 璁剧疆鍝嶅簲澶�
+ response.setContentType("application/octet-stream");
+ response.setHeader("Content-Disposition", "attachment; filename=" + attachment.getFileName());
+ response.setContentLengthLong(file.length());
+
+ // 璇诲彇鏂囦欢骞惰緭鍑�
+ try (FileInputStream fis = new FileInputStream(file);
+ OutputStream os = response.getOutputStream()) {
+ byte[] buffer = new byte[4096];
+ int bytesRead;
+ while ((bytesRead = fis.read(buffer)) != -1) {
+ os.write(buffer, 0, bytesRead);
+ }
+ os.flush();
+ }
+ } catch (Exception e) {
+ logger.error("涓嬭浇闄勪欢澶辫触", e);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ }
}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wechat/WechatController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wechat/WechatController.java
new file mode 100644
index 0000000..d5b8c99
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/wechat/WechatController.java
@@ -0,0 +1,42 @@
+package com.ruoyi.web.controller.wechat;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.config.WechatConfig;
+import com.ruoyi.common.utils.WechatUtils;
+
+/**
+ * 寰俊鎺ュ彛Controller
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/wechat")
+public class WechatController extends BaseController {
+
+ @Autowired
+ private WechatConfig wechatConfig;
+
+ /**
+ * 鑾峰彇寰俊AccessToken
+ */
+ @GetMapping("/accessToken")
+ public AjaxResult getAccessToken() {
+ try {
+ String accessToken = WechatUtils.getAccessToken(
+ wechatConfig.getAppId(),
+ wechatConfig.getAppSecret()
+ );
+ if (accessToken == null || accessToken.isEmpty()) {
+ return error("鑾峰彇寰俊AccessToken澶辫触");
+ }
+ return success(accessToken);
+ } catch (Exception e) {
+ return error("鑾峰彇寰俊AccessToken寮傚父锛�" + e.getMessage());
+ }
+ }
+}
diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml
index 735283f..8c0477f 100644
--- a/ruoyi-admin/src/main/resources/application-dev.yml
+++ b/ruoyi-admin/src/main/resources/application-dev.yml
@@ -97,6 +97,10 @@
# 鏃х郴缁熷熀纭�URL (蹇呴』閰嶇疆)
# 绀轰緥: http://192.168.1.100:8080 鎴� http://legacy.yourdomain.com
base-url: http://120.25.98.119:8083
+ # 鏂囦欢涓婁紶URL
+ fileUploadUrl: http://120.25.98.119:8083/weixin/upload_file.php
+ # 鏂囦欢涓嬭浇URL
+ fileServerUrl: http://120.25.98.119:8083
# 鎬ユ晳杞繍鍒涘缓鎺ュ彛璺緞 (鍙�夛紝榛樿鍊煎涓�)
emergency-create-path: /admin_save_19.gds
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index bd5fb75..18f8574 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -56,7 +56,7 @@
basename: i18n/messages
profiles:
# 鐜 dev|test|prod
- active: prod
+ active: dev
# 鏂囦欢涓婁紶
servlet:
multipart:
@@ -146,11 +146,14 @@
apiUrl: http://120.25.98.119:8084/v1/ #娴嬭瘯鐜锛歭ocalhost:8011
# 寰俊閰嶇疆
-wechat:
+evaluationWechat:
appId: wx70f6a7346ee842c0
appSecret: 2d6c59de85e876b7eadebeba62e5417a
redirectUri: http://yourdomain.com/evaluation
-
+# 璋冨害鐢ㄧ殑weixin閰嶇疆
+transferConfigWeixin:
+ appId: wx40692cc44953a8cb
+ appSecret: 9638b7d8bb988e4daaac7ac35457f296
# 鑵捐鍦板浘閰嶇疆
tencent:
map:
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/LegacySystemConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/LegacySystemConfig.java
index 5038fe6..02ef3e2 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/config/LegacySystemConfig.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/LegacySystemConfig.java
@@ -24,6 +24,10 @@
/** 浠诲姟鐘舵�佹煡璇㈡帴鍙h矾寰勶紙宸插純鐢紝鐩存帴鏌ヨSQL Server鏁版嵁搴擄級 */
@Deprecated
private String statusQueryPath = "/task_status_query.asp";
+
+ private String fileUploadUrl;
+
+ private String fileServerUrl;
/** 杩炴帴瓒呮椂鏃堕棿(姣) */
private int connectTimeout = 30000;
@@ -41,6 +45,21 @@
return baseUrl;
}
+ public String getFileUploadUrl(){
+ return fileUploadUrl;
+ }
+
+ public void setFileUploadUrl(String fileUploadUrl){
+ this.fileUploadUrl = fileUploadUrl;
+ }
+
+ public String getFileServerUrl(){
+ return fileServerUrl;
+ }
+
+ public void setFileServerUrl(String fileServerUrl){
+ this.fileServerUrl = fileServerUrl;
+ }
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/WechatConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/WechatConfig.java
new file mode 100644
index 0000000..b60bb7a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/WechatConfig.java
@@ -0,0 +1,37 @@
+package com.ruoyi.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 寰俊灏忕▼搴忛厤缃被锛堢敤浜庨檮浠朵笂浼犵瓑灏忕▼搴忓姛鑳斤級
+ * 閰嶇疆鏉ユ簮锛歵ransferConfig.weixin
+ *
+ * @author ruoyi
+ */
+@Component
+@ConfigurationProperties(prefix = "transfer-config-weixin")
+public class WechatConfig {
+
+ /** 寰俊灏忕▼搴廇ppID */
+ private String appId;
+
+ /** 寰俊灏忕▼搴廇ppSecret */
+ private String appSecret;
+
+ public String getAppId() {
+ return appId;
+ }
+
+ public void setAppId(String appId) {
+ this.appId = appId;
+ }
+
+ public String getAppSecret() {
+ return appSecret;
+ }
+
+ public void setAppSecret(String appSecret) {
+ this.appSecret = appSecret;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/WechatMpConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/WechatMpConfig.java
new file mode 100644
index 0000000..2a3c209
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/WechatMpConfig.java
@@ -0,0 +1,47 @@
+package com.ruoyi.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 寰俊鍏紬鍙烽厤缃被锛堢敤浜庣綉椤垫巿鏉冦�佽瘎浠风瓑鍏紬鍙峰姛鑳斤級
+ *
+ * @author ruoyi
+ */
+@Component
+@ConfigurationProperties(prefix = "evaluation-wechat")
+public class WechatMpConfig {
+
+ /** 寰俊鍏紬鍙稟ppID */
+ private String appId;
+
+ /** 寰俊鍏紬鍙稟ppSecret */
+ private String appSecret;
+
+ /** 寰俊鎺堟潈鍥炶皟鍦板潃 */
+ private String redirectUri;
+
+ public String getAppId() {
+ return appId;
+ }
+
+ public void setAppId(String appId) {
+ this.appId = appId;
+ }
+
+ public String getAppSecret() {
+ return appSecret;
+ }
+
+ public void setAppSecret(String appSecret) {
+ this.appSecret = appSecret;
+ }
+
+ public String getRedirectUri() {
+ return redirectUri;
+ }
+
+ public void setRedirectUri(String redirectUri) {
+ this.redirectUri = redirectUri;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/InputStreamBase64Converter.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/InputStreamBase64Converter.java
new file mode 100644
index 0000000..88a1591
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/InputStreamBase64Converter.java
@@ -0,0 +1,35 @@
+package com.ruoyi.common.utils;
+
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.Base64;
+
+public class InputStreamBase64Converter {
+
+ /**
+ * 灏咺nputStream杞崲涓築ase64瀛楃涓�
+ */
+ public static String inputStreamToBase64(InputStream inputStream) throws Exception {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ byte[] buffer = new byte[4096];
+ int bytesRead;
+
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+
+ byte[] bytes = outputStream.toByteArray();
+ return Base64.getEncoder().encodeToString(bytes);
+ }
+
+ /**
+ * 灏咮ase64瀛楃涓茶浆鎹㈠洖InputStream
+ */
+ public static InputStream base64ToInputStream(String base64String) {
+ byte[] bytes = Base64.getDecoder().decode(base64String);
+ return new ByteArrayInputStream(bytes);
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
index feb555a..1094430 100644
--- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
@@ -1,16 +1,10 @@
package com.ruoyi.common.utils.http;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.net.ConnectException;
-import java.net.SocketTimeoutException;
-import java.net.URL;
-import java.net.URLConnection;
+import java.io.*;
+import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
+import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
@@ -33,6 +27,43 @@
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
public static final int DEFAULT_READ_TIMEOUT = 60000;
+ private static final String BOUNDARY_PREFIX = "----WebKitFormBoundary";
+ private static final String LINE_END = "\r\n";
+ private static final String TWO_HYPHENS = "--";
+
+
+ /**
+ * 鐢熸垚鍞竴鐨刡oundary
+ */
+ private static String generateBoundary() {
+ return BOUNDARY_PREFIX + System.currentTimeMillis();
+ }
+
+ /**
+ * 鏍规嵁鏂囦欢鍚嶈幏鍙朇ontent-Type
+ */
+ private static String getContentType(String fileName) {
+ if (fileName == null) {
+ return "application/octet-stream";
+ }
+
+ String extension = fileName.toLowerCase();
+ if (extension.endsWith(".jpg") || extension.endsWith(".jpeg")) {
+ return "image/jpeg";
+ } else if (extension.endsWith(".png")) {
+ return "image/png";
+ } else if (extension.endsWith(".gif")) {
+ return "image/gif";
+ } else if (extension.endsWith(".pdf")) {
+ return "application/pdf";
+ } else if (extension.endsWith(".doc")) {
+ return "application/msword";
+ } else if (extension.endsWith(".docx")) {
+ return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
+ } else {
+ return "application/octet-stream";
+ }
+ }
/**
* 鍚戞寚瀹� URL 鍙戦�丟ET鏂规硶鐨勮姹�
@@ -299,4 +330,138 @@
return true;
}
}
+
+ /**
+ * 鍙戦�佹枃浠朵笂浼犺姹�
+ *
+ * @param url 璇锋眰URL
+ * @param params 璇锋眰鍙傛暟锛堝寘鍚枃浠舵祦锛�
+ * @return 鍝嶅簲鍐呭
+ */
+ public static String postFile(String url, Map<String, Object> params) {
+ return postFile(url, params, null);
+ }
+
+ /**
+ * 鍙戦�佹枃浠朵笂浼犺姹傦紙鏀寔鑷畾涔夋枃浠跺悕锛�
+ *
+ * @param url 璇锋眰URL
+ * @param params 璇锋眰鍙傛暟锛堝寘鍚枃浠舵祦锛�
+ * @param fileName 鏂囦欢鍚嶏紙鍙�夛紝濡傛灉涓簄ull鍒欎娇鐢ㄥ弬鏁伴敭鍚嶏級
+ * @return 鍝嶅簲鍐呭
+ */
+ public static String postFile(String url, Map<String, Object> params, String fileName) {
+ HttpURLConnection connection = null;
+ try {
+ // 鐢熸垚鍞竴鐨刡oundary
+ String boundary = generateBoundary();
+
+ log.info("寮�濮嬫枃浠朵笂浼� - URL: {}, fileName: {}, boundary: {}", url, fileName, boundary);
+ log.info("鍙傛暟鏁伴噺: {}", params.size());
+ for (Map.Entry<String, Object> entry : params.entrySet()) {
+ log.info("鍙傛暟: {} = {}", entry.getKey(), entry.getValue() instanceof InputStream ? "InputStream" : entry.getValue());
+ }
+
+ // 鍒涘缓杩炴帴
+ URL requestUrl = new URL(url);
+ connection = (HttpURLConnection) requestUrl.openConnection();
+
+ // 璁剧疆璇锋眰灞炴��
+ connection.setRequestMethod("POST");
+ connection.setDoOutput(true);
+ connection.setDoInput(true);
+ connection.setUseCaches(false);
+ connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
+ connection.setRequestProperty("Accept", "application/json");
+ connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
+ connection.setRequestProperty("Connection", "Keep-Alive");
+ connection.setRequestProperty("Accept-Charset", "utf-8");
+ connection.setConnectTimeout(30000);
+ connection.setReadTimeout(60000);
+
+ // 鏋勫缓璇锋眰浣�
+ try (OutputStream outputStream = connection.getOutputStream();
+ PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8), true)) {
+
+ // 鍐欏叆鏅�氬弬鏁�
+ for (Map.Entry<String, Object> entry : params.entrySet()) {
+ Object value = entry.getValue();
+ if (!(value instanceof InputStream)) {
+ writer.append(TWO_HYPHENS).append(boundary).append(LINE_END);
+ writer.append("Content-Disposition: form-data; name=\"").append(entry.getKey()).append("\"").append(LINE_END);
+ writer.append("Content-Type: text/plain; charset=UTF-8").append(LINE_END);
+ writer.append(LINE_END);
+ writer.append(value.toString()).append(LINE_END);
+ writer.flush();
+ }
+ }
+
+ // 鍐欏叆鏂囦欢鍙傛暟
+ for (Map.Entry<String, Object> entry : params.entrySet()) {
+ Object value = entry.getValue();
+ if (value instanceof InputStream) {
+ // 纭畾鏂囦欢鍚�
+ String actualFileName = fileName != null ? fileName : entry.getKey();
+
+ writer.append(TWO_HYPHENS).append(boundary).append(LINE_END);
+ writer.append("Content-Disposition: form-data; name=\"").append(entry.getKey()).append("\"; filename=\"").append(actualFileName).append("\"").append(LINE_END);
+ writer.append("Content-Type: ").append(getContentType(actualFileName)).append(LINE_END);
+ writer.append(LINE_END);
+ writer.flush();
+
+ // 鍐欏叆鏂囦欢鍐呭
+ try (InputStream inputStream = (InputStream) value) {
+ byte[] buffer = new byte[4096];
+ int bytesRead;
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+ outputStream.flush();
+ }
+
+ writer.append(LINE_END);
+ writer.flush();
+ }
+ }
+
+ // 鍐欏叆缁撴潫鏍囪
+ writer.append(TWO_HYPHENS).append(boundary).append(TWO_HYPHENS).append(LINE_END);
+ writer.flush();
+ }
+
+ // 鑾峰彇鍝嶅簲
+ int responseCode = connection.getResponseCode();
+ log.info("鏂囦欢涓婁紶鍝嶅簲鐮侊細{}", responseCode);
+
+ // 璇诲彇鍝嶅簲鍐呭
+ StringBuilder response = new StringBuilder();
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(
+ responseCode == HttpURLConnection.HTTP_OK ?
+ connection.getInputStream() :
+ connection.getErrorStream(),
+ StandardCharsets.UTF_8))) {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ response.append(line);
+ }
+ }
+
+ if (responseCode != HttpURLConnection.HTTP_OK) {
+ log.error("鏂囦欢涓婁紶澶辫触锛屽搷搴旂爜锛歿}锛屽搷搴斿唴瀹癸細{}", responseCode, response.toString());
+ throw new RuntimeException("鏂囦欢涓婁紶澶辫触锛屽搷搴旂爜: " + responseCode + "锛屽搷搴斿唴瀹�: " + response.toString());
+ }
+
+ log.info("鏂囦欢涓婁紶鎴愬姛锛屽搷搴旓細{}", response.toString());
+ return response.toString();
+
+ } catch (Exception e) {
+ log.error("鏂囦欢涓婁紶寮傚父锛歿}", e.getMessage(), e);
+ throw new RuntimeException("鏂囦欢涓婁紶澶辫触: " + e.getMessage(), e);
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/ImageData.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/ImageData.java
new file mode 100644
index 0000000..e6af077
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/ImageData.java
@@ -0,0 +1,92 @@
+package com.ruoyi.system.domain;
+
+
+import com.ruoyi.common.core.domain.BaseEntity;
+import lombok.Data;
+
+import java.util.Date;
+import com.ruoyi.common.annotation.Excel;
+/**
+ * 鍥剧墖鏁版嵁瀵硅薄 ImageData
+ */
+@Data
+public class ImageData extends BaseEntity {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 涓婚敭ID
+ */
+ private Long id;
+
+ /**
+ * 璋冨害鍗旾D
+ */
+ @Excel(name = "璋冨害鍗旾D")
+ private Long dOrdIDDt;
+
+ /**
+ * 鏈嶅姟鍗旾D
+ */
+ @Excel(name = "鏈嶅姟鍗旾D")
+ private Long sOrdIDDt;
+
+ /**
+ * 鍥剧墖绫诲瀷
+ */
+ @Excel(name = "鍥剧墖绫诲瀷")
+ private Integer imageType;
+
+ /**
+ * 鍥剧墖URL
+ */
+ @Excel(name = "鍥剧墖URL")
+ private String imageUrl;
+
+ /**
+ * 鍥剧墖URLs
+ */
+ @Excel(name = "鍥剧墖URLs")
+ private String imageUrls;
+
+ /**
+ * 鍥剧墖搴︽暟
+ */
+ @Excel(name = "鍥剧墖搴︽暟")
+ private Integer imageDeg;
+
+ /**
+ * 涓婁紶鍥剧墖鏃堕棿
+ */
+ @Excel(name = "涓婁紶鍥剧墖鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+ private Date upImageTime;
+
+ /**
+ * 涓婁紶鍥剧墖OA鐢ㄦ埛ID
+ */
+ @Excel(name = "涓婁紶鍥剧墖OA鐢ㄦ埛ID")
+ private Integer upImageOAid;
+
+ /**
+ * 鍥剧墖鍒犻櫎鏍囪
+ */
+ @Excel(name = "鍥剧墖鍒犻櫎鏍囪")
+ private Integer imageDel;
+
+ /**
+ * 鏄惁AP
+ */
+ @Excel(name = "鏄惁AP")
+ private Integer isAP;
+
+ /**
+ * AP ID
+ */
+ @Excel(name = "AP ID")
+ private Integer isAP_ID;
+
+ /**
+ * AP鏃堕棿
+ */
+ @Excel(name = "AP鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+ private Date isAP_Time;
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAttachment.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAttachment.java
index 6dd5bff..51a83db 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAttachment.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTaskAttachment.java
@@ -37,6 +37,10 @@
@Excel(name = "鏂囦欢绫诲瀷")
private String fileType;
+ /** 闄勪欢鍒嗙被 */
+ @Excel(name = "闄勪欢鍒嗙被")
+ private String attachmentCategory;
+
/** 涓婁紶鏃堕棿 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name = "涓婁紶鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
@@ -94,6 +98,14 @@
return fileType;
}
+ public void setAttachmentCategory(String attachmentCategory) {
+ this.attachmentCategory = attachmentCategory;
+ }
+
+ public String getAttachmentCategory() {
+ return attachmentCategory;
+ }
+
public void setUploadTime(Date uploadTime) {
this.uploadTime = uploadTime;
}
@@ -119,6 +131,7 @@
", filePath='" + filePath + '\'' +
", fileSize=" + fileSize +
", fileType='" + fileType + '\'' +
+ ", attachmentCategory='" + attachmentCategory + '\'' +
", uploadTime=" + uploadTime +
", uploadBy='" + uploadBy + '\'' +
'}';
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/enums/ImageTypeEnum.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/enums/ImageTypeEnum.java
new file mode 100644
index 0000000..425888d
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/enums/ImageTypeEnum.java
@@ -0,0 +1,64 @@
+package com.ruoyi.system.domain.enums;
+
+public enum ImageTypeEnum {
+
+ DEFAULT(0, "榛樿"),
+
+ INFORMED_CONSENT(1, "鐭ユ儏鍚屾剰涔�"),
+ BRZL(2, "鐥呬汉璧勬枡"),
+ CZJL(3, "鎿嶄綔璁板綍"),
+ CCQ(4, "鍑鸿溅鍓�"),
+ CCH(5, "鍑鸿溅鍚�"),
+ SEAT_BELT(6, "缁戝畨鍏ㄥ甫鍥剧墖");
+// 鐭ユ儏鍚屾剰涔� 1
+// 鐥呬汉璧勬枡 2
+// 鎿嶄綔璁板綍 3
+// 鍑鸿溅鍓� 4
+// 鍑鸿溅鍚� 5
+// 绯诲畨鍏ㄥ甫 6
+ private final Integer code;
+ private final String description;
+
+ ImageTypeEnum(Integer code, String description) {
+ this.code = code;
+ this.description = description;
+ }
+
+ public Integer getCode() {
+ return code;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * 鏍规嵁浠g爜鑾峰彇鏋氫妇
+ */
+ public static ImageTypeEnum getByCode(Integer code) {
+ if (code == null) {
+ return DEFAULT;
+ }
+
+ for (ImageTypeEnum type : values()) {
+ if (type.getCode().equals(code)) {
+ return type;
+ }
+ }
+ return DEFAULT;
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁涓虹煡鎯呭悓鎰忎功
+ */
+ public boolean isInformedConsent() {
+ return this == INFORMED_CONSENT;
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁涓虹粦瀹夊叏甯﹀浘鐗�
+ */
+ public boolean isSeatBelt() {
+ return this == SEAT_BELT;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadResponse.java b/ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadResponse.java
new file mode 100644
index 0000000..7038649
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadResponse.java
@@ -0,0 +1,41 @@
+package com.ruoyi.system.file;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class FileUploadResponse implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ @JsonProperty("success")
+ private boolean success;
+
+ @JsonProperty("message")
+ private String message;
+
+ @JsonProperty("filePath")
+ private String filePath;
+
+ @JsonProperty("thumbnailPath")
+ private String thumbnailPath;
+
+
+ public static FileUploadResponse error(String error) {
+ FileUploadResponse response = new FileUploadResponse();
+ response.setSuccess(false);
+ response.setMessage(error);
+ return response;
+ }
+ public static FileUploadResponse success(String file,String message) {
+ FileUploadResponse response = new FileUploadResponse();
+ response.setSuccess(true);
+ response.setFilePath(file);
+ response.setMessage(message);
+
+ return response;
+ }
+
+
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadServiceImpl.java
new file mode 100644
index 0000000..1abb2aa
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/file/FileUploadServiceImpl.java
@@ -0,0 +1,549 @@
+package com.ruoyi.system.file;
+
+import com.ruoyi.common.config.LegacySystemConfig;
+import com.ruoyi.common.utils.http.HttpUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.*;
+
+import java.io.*;
+
+@Service
+public class FileUploadServiceImpl implements IFileUploadService {
+
+ private static final Logger log = LoggerFactory.getLogger(FileUploadServiceImpl.class);
+
+
+ @Autowired
+ private LegacySystemConfig legacyConfig;
+
+
+ @Override
+ public FileUploadResponse uploadLocalFile(File file, String targetPath) {
+ if (file == null || !file.exists()) {
+ return FileUploadResponse.error("鏂囦欢涓嶅瓨鍦�");
+ }
+
+ try (FileInputStream fis = new FileInputStream(file)) {
+ return uploadInputStream(fis, file.getName(), targetPath);
+ } catch (IOException e) {
+ log.error("璇诲彇鏈湴鏂囦欢澶辫触: {}", file.getAbsolutePath(), e);
+ return FileUploadResponse.error("璇诲彇鏂囦欢澶辫触: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public FileUploadResponse uploadMultipartFile(MultipartFile multipartFile, String targetPath) {
+ if (multipartFile == null || multipartFile.isEmpty()) {
+ return FileUploadResponse.error("鏂囦欢涓虹┖");
+ }
+
+ try (InputStream inputStream = multipartFile.getInputStream()) {
+ return uploadInputStream(inputStream, multipartFile.getOriginalFilename(), targetPath);
+ } catch (IOException e) {
+ log.error("璇诲彇MultipartFile澶辫触", e);
+ return FileUploadResponse.error("璇诲彇鏂囦欢澶辫触: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public FileUploadResponse uploadBytes(byte[] fileBytes, String fileName, String targetPath) {
+ if (fileBytes == null || fileBytes.length == 0) {
+ return FileUploadResponse.error("鏂囦欢瀛楄妭鏁扮粍涓虹┖");
+ }
+
+ try (ByteArrayInputStream bis = new ByteArrayInputStream(fileBytes)) {
+ return uploadInputStream(bis, fileName, targetPath);
+ } catch (IOException e) {
+ log.error("澶勭悊瀛楄妭鏁扮粍澶辫触", e);
+ return FileUploadResponse.error("澶勭悊鏂囦欢澶辫触: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public FileUploadResponse uploadInputStream(InputStream inputStream, String fileName, String targetPath) {
+ if (inputStream == null) {
+ return FileUploadResponse.error("杈撳叆娴佷负绌�");
+ }
+
+ try {
+ // 鏋勫缓璇锋眰鍙傛暟
+ Map<String, Object> params = new HashMap<>();
+ params.put("file", inputStream);
+ params.put("uploadFileName", targetPath);
+
+ log.info("寮�濮嬩笂浼犳枃浠跺埌PHP鎺ュ彛: fileName={}, targetPath={}", fileName, targetPath);
+
+ // 璋冪敤PHP涓婁紶鎺ュ彛
+ String response = HttpUtils.postFile(legacyConfig.getFileServerUrl(), params, fileName);
+
+ log.info("PHP鎺ュ彛鍝嶅簲: {}", response);
+
+ // 瑙f瀽鍝嶅簲
+ return parseUploadResponse(response);
+
+ } catch (Exception e) {
+ log.error("涓婁紶鏂囦欢鍒癙HP鎺ュ彛澶辫触: fileName={}, targetPath={}", fileName, targetPath, e);
+ return FileUploadResponse.error("涓婁紶澶辫触: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public FileUploadResponse uploadFromUrl(String fileUrl, String targetPath) {
+ if (fileUrl == null || fileUrl.trim().isEmpty()) {
+ return FileUploadResponse.error("鏂囦欢URL涓虹┖");
+ }
+
+ try {
+ // 浠嶶RL涓嬭浇鏂囦欢
+ byte[] fileBytes = downloadFromUrl(fileUrl);
+ if (fileBytes == null || fileBytes.length == 0) {
+ return FileUploadResponse.error("浠嶶RL涓嬭浇鏂囦欢澶辫触");
+ }
+
+ // 浠嶶RL涓彁鍙栨枃浠跺悕
+ String fileName = extractFileNameFromUrl(fileUrl);
+
+ // 涓婁紶鏂囦欢
+ return uploadBytes(fileBytes, fileName, targetPath);
+
+ } catch (Exception e) {
+ log.error("浠嶶RL涓婁紶鏂囦欢澶辫触: fileUrl={}, targetPath={}", fileUrl, targetPath, e);
+ return FileUploadResponse.error("浠嶶RL涓婁紶澶辫触: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public FileUploadResponse uploadFromWechat(String accessToken, String mediaId, String targetPath) {
+ if (accessToken == null || mediaId == null) {
+ return FileUploadResponse.error("寰俊鍙傛暟涓虹┖");
+ }
+
+ try {
+ // 浠庡井淇PI涓嬭浇鏂囦欢
+ byte[] fileBytes = downloadFromWechat(accessToken, mediaId);
+ if (fileBytes == null || fileBytes.length == 0) {
+ return FileUploadResponse.error("浠庡井淇′笅杞芥枃浠跺け璐�");
+ }
+
+ // 鐢熸垚鏂囦欢鍚�
+ String fileName = "wechat_" + mediaId + ".jpg";
+
+ // 涓婁紶鏂囦欢
+ return uploadBytes(fileBytes, fileName, targetPath);
+
+ } catch (Exception e) {
+ log.error("浠庡井淇′笂浼犳枃浠跺け璐�: mediaId={}, targetPath={}", mediaId, targetPath, e);
+ return FileUploadResponse.error("浠庡井淇′笂浼犲け璐�: " + e.getMessage());
+ }
+ }
+
+ @Override
+ public boolean fileExists(String filePath) {
+ if (filePath == null || filePath.trim().isEmpty()) {
+ return false;
+ }
+
+ try {
+ // 鏋勫缓瀹屾暣鐨勬枃浠惰矾寰�
+ String fullPath = legacyConfig.getFileServerUrl() + "/" + filePath;
+ File file = new File(fullPath);
+ return file.exists() && file.isFile();
+ } catch (Exception e) {
+ log.error("妫�鏌ユ枃浠舵槸鍚﹀瓨鍦ㄥけ璐�: {}", filePath, e);
+ return false;
+ }
+ }
+
+ @Override
+ public boolean deleteFile(String filePath) {
+ if (filePath == null || filePath.trim().isEmpty()) {
+ return false;
+ }
+
+ try {
+ // 鏋勫缓瀹屾暣鐨勬枃浠惰矾寰�
+ String fullPath = legacyConfig.getFileServerUrl() + "/" + filePath;
+ File file = new File(fullPath);
+
+ if (file.exists() && file.isFile()) {
+ return file.delete();
+ }
+ return false;
+ } catch (Exception e) {
+ log.error("鍒犻櫎鏂囦欢澶辫触: {}", filePath, e);
+ return false;
+ }
+ }
+
+ @Override
+ public String getFileUrl(String filePath) {
+ if (filePath == null || filePath.trim().isEmpty()) {
+ return null;
+ }
+
+ // 鏋勫缓鏂囦欢璁块棶URL
+ return legacyConfig.getFileServerUrl() + "/" + filePath;
+ }
+
+ /**
+ * 浠嶶RL涓嬭浇鏂囦欢
+ */
+ private byte[] downloadFromUrl(String fileUrl) throws IOException {
+ URL url = new URL(fileUrl);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(10000);
+ connection.setReadTimeout(30000);
+
+ try (InputStream inputStream = connection.getInputStream();
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
+
+ byte[] buffer = new byte[4096];
+ int bytesRead;
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+
+ return outputStream.toByteArray();
+ } finally {
+ connection.disconnect();
+ }
+ }
+
+ /**
+ * 浠庡井淇PI涓嬭浇鏂囦欢
+ */
+ private byte[] downloadFromWechat(String accessToken, String mediaId) throws IOException {
+ String wechatUrl = String.format(
+ "https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s",
+ accessToken, mediaId
+ );
+
+ return downloadFromUrl(wechatUrl);
+ }
+
+ /**
+ * 浠嶶RL涓彁鍙栨枃浠跺悕
+ */
+ private String extractFileNameFromUrl(String fileUrl) {
+ try {
+ String fileName = fileUrl.substring(fileUrl.lastIndexOf('/') + 1);
+ // 绉婚櫎鏌ヨ鍙傛暟
+ if (fileName.contains("?")) {
+ fileName = fileName.substring(0, fileName.indexOf('?'));
+ }
+ return fileName.isEmpty() ? "downloaded_file" : fileName;
+ } catch (Exception e) {
+ return "downloaded_file";
+ }
+ }
+
+ /**
+ * 瑙f瀽涓婁紶鍝嶅簲
+ */
+ private FileUploadResponse parseUploadResponse(String response) {
+ if (response == null || response.trim().isEmpty()) {
+ return FileUploadResponse.error("PHP鎺ュ彛杩斿洖绌哄搷搴�");
+ }
+
+ try {
+ log.info("寮�濮嬭В鏋怭HP鍝嶅簲: {}", response);
+
+ // 鏍规嵁PHP鎺ュ彛鐨勫疄闄呰繑鍥炴牸寮忚繘琛岃В鏋�
+ // PHP杩斿洖鏍煎紡: {"success": true, "message": "鏂囦欢涓婁紶鎴愬姛", "data": {...}}
+ if (response.contains("\"success\":true") || response.contains("success")) {
+ // 鎻愬彇鏂囦欢璺緞鍜岀缉鐣ュ浘璺緞
+ String filePath = extractFilePathFromResponse(response);
+ String thumbnailPath = extractThumbnailPathFromResponse(response);
+
+ log.info("瑙f瀽缁撴灉 - filePath: {}, thumbnailPath: {}", filePath, thumbnailPath);
+
+ // 鍒涘缓鍝嶅簲瀵硅薄
+ FileUploadResponse uploadResponse = FileUploadResponse.success(filePath, "涓婁紶鎴愬姛");
+ if (thumbnailPath != null && !thumbnailPath.isEmpty()) {
+ uploadResponse.setThumbnailPath(thumbnailPath);
+ }
+
+ return uploadResponse;
+ } else {
+ // 鎻愬彇閿欒淇℃伅
+ String errorMessage = extractErrorMessageFromResponse(response);
+ log.error("涓婁紶澶辫触锛岄敊璇俊鎭�: {}", errorMessage);
+ return FileUploadResponse.error(errorMessage != null ? errorMessage : "涓婁紶澶辫触");
+ }
+ } catch (Exception e) {
+ log.error("瑙f瀽涓婁紶鍝嶅簲澶辫触: {}", response, e);
+ return FileUploadResponse.error("瑙f瀽鍝嶅簲澶辫触: " + e.getMessage());
+ }
+ }
+
+ /**
+ * 浠庡搷搴斾腑鎻愬彇鏂囦欢璺緞
+ */
+ private String extractFilePathFromResponse(String response) {
+ // 瑙f瀽PHP鎺ュ彛杩斿洖鐨凧SON鏍煎紡: {"success": true, "data": {"filePath": "..."}}
+ try {
+ if (response.contains("\"data\":")) {
+ // 鎵惧埌data瀵硅薄
+ int dataStart = response.indexOf("\"data\":{") + 7;
+ if (dataStart > 6) {
+ // 鍦╠ata瀵硅薄涓煡鎵緁ilePath
+ String dataSection = response.substring(dataStart);
+ if (dataSection.contains("\"filePath\":")) {
+ int start = dataSection.indexOf("\"filePath\":\"") + 12;
+ int end = dataSection.indexOf("\"", start);
+ if (start > 11 && end > start) {
+ String filePath = dataSection.substring(start, end);
+ log.info("鎻愬彇鍒版枃浠惰矾寰�: {}", filePath);
+ return filePath;
+ }
+ }
+ }
+ }
+
+ // 鍏煎鏃ф牸寮忥紝鐩存帴鏌ユ壘filePath
+ if (response.contains("\"filePath\":")) {
+ int start = response.indexOf("\"filePath\":\"") + 12;
+ int end = response.indexOf("\"", start);
+ if (start > 11 && end > start) {
+ String filePath = response.substring(start, end);
+ log.info("鎻愬彇鍒版枃浠惰矾寰�(鏃ф牸寮�): {}", filePath);
+ return filePath;
+ }
+ }
+ } catch (Exception e) {
+ log.error("鎻愬彇鏂囦欢璺緞澶辫触: {}", response, e);
+ }
+ return null;
+ }
+
+ /**
+ * 浠庡搷搴斾腑鎻愬彇缂╃暐鍥捐矾寰�
+ */
+ private String extractThumbnailPathFromResponse(String response) {
+ // 瑙f瀽PHP鎺ュ彛杩斿洖鐨凧SON鏍煎紡: {"success": true, "data": {"thumbnailPath": "..."}}
+ try {
+ if (response.contains("\"data\":")) {
+ // 鎵惧埌data瀵硅薄
+ int dataStart = response.indexOf("\"data\":{") + 7;
+ if (dataStart > 6) {
+ // 鍦╠ata瀵硅薄涓煡鎵総humbnailPath
+ String dataSection = response.substring(dataStart);
+ if (dataSection.contains("\"thumbnailPath\":")) {
+ int start = dataSection.indexOf("\"thumbnailPath\":\"") + 17;
+ int end = dataSection.indexOf("\"", start);
+ if (start > 16 && end > start) {
+ String thumbnailPath = dataSection.substring(start, end);
+ log.info("鎻愬彇鍒扮缉鐣ュ浘璺緞: {}", thumbnailPath);
+ return thumbnailPath;
+ }
+ }
+ }
+ }
+
+ // 鍏煎鏃ф牸寮忥紝鐩存帴鏌ユ壘thumbnailPath
+ if (response.contains("\"thumbnailPath\":")) {
+ int start = response.indexOf("\"thumbnailPath\":\"") + 17;
+ int end = response.indexOf("\"", start);
+ if (start > 16 && end > start) {
+ String thumbnailPath = response.substring(start, end);
+ log.info("鎻愬彇鍒扮缉鐣ュ浘璺緞(鏃ф牸寮�): {}", thumbnailPath);
+ return thumbnailPath;
+ }
+ }
+ } catch (Exception e) {
+ log.error("鎻愬彇缂╃暐鍥捐矾寰勫け璐�: {}", response, e);
+ }
+ return null;
+ }
+
+ /**
+ * 浠庡搷搴斾腑鎻愬彇閿欒淇℃伅
+ */
+ private String extractErrorMessageFromResponse(String response) {
+ // 瑙f瀽PHP鎺ュ彛杩斿洖鐨凧SON鏍煎紡: {"success": false, "message": "閿欒淇℃伅"}
+ try {
+ if (response.contains("\"message\":")) {
+ int start = response.indexOf("\"message\":\"") + 11;
+ int end = response.indexOf("\"", start);
+ if (start > 10 && end > start) {
+ String errorMessage = response.substring(start, end);
+ log.info("鎻愬彇鍒伴敊璇俊鎭�: {}", errorMessage);
+ return errorMessage;
+ }
+ }
+ } catch (Exception e) {
+ log.error("鎻愬彇閿欒淇℃伅澶辫触: {}", response, e);
+ }
+ return null;
+ }
+
+ /**
+ * 鐢熸垚缂╃暐鍥�
+ *
+ * @param sourcePath 婧愬浘鐗囪矾寰�
+ * @param targetPath 鐩爣缂╃暐鍥捐矾寰�
+ * @param width 瀹藉害
+ * @param height 楂樺害锛�0琛ㄧず鎸夋瘮渚嬬缉鏀撅級
+ * @return 鏄惁鐢熸垚鎴愬姛
+ */
+ private boolean createThumbnail(String sourcePath, String targetPath, int width, int height) {
+ try {
+ // 璇诲彇婧愬浘鐗�
+ BufferedImage sourceImage = ImageIO.read(new File(sourcePath));
+ if (sourceImage == null) {
+ log.error("鏃犳硶璇诲彇婧愬浘鐗囷細{}", sourcePath);
+ return false;
+ }
+
+ // 璁$畻缂╃暐鍥惧昂瀵�
+ int sourceWidth = sourceImage.getWidth();
+ int sourceHeight = sourceImage.getHeight();
+
+ if (height == 0) {
+ height = (int) Math.floor((double) width / sourceWidth * sourceHeight);
+ } else if (width == 0) {
+ width = (int) Math.floor((double) height / sourceHeight * sourceWidth);
+ }
+
+ // 鍒涘缓缂╃暐鍥�
+ BufferedImage thumbnailImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g2d = thumbnailImage.createGraphics();
+
+ // 璁剧疆娓叉煋璐ㄩ噺
+ g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+ g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ // 缁樺埗缂╃暐鍥�
+ g2d.drawImage(sourceImage, 0, 0, width, height, null);
+ g2d.dispose();
+
+ // 淇濆瓨缂╃暐鍥�
+ String extension = getFileExtension(sourcePath);
+ return ImageIO.write(thumbnailImage, extension, new File(targetPath));
+
+ } catch (Exception e) {
+ log.error("鐢熸垚缂╃暐鍥惧け璐ワ細sourcePath={}, targetPath={}", sourcePath, targetPath, e);
+ return false;
+ }
+ }
+
+ /**
+ * 鑾峰彇鏂囦欢鎵╁睍鍚�
+ */
+ private String getFileExtension(String filePath) {
+ int lastDotIndex = filePath.lastIndexOf('.');
+ if (lastDotIndex > 0) {
+ return filePath.substring(lastDotIndex + 1).toLowerCase();
+ }
+ return "jpg"; // 榛樿鎵╁睍鍚�
+ }
+
+ /**
+ * 鏈湴鏂囦欢涓婁紶锛堝寘鍚缉鐣ュ浘鐢熸垚锛�
+ */
+ public FileUploadResponse uploadLocalFileWithThumbnail(File file, String targetPath) {
+ if (file == null || !file.exists()) {
+ return FileUploadResponse.error("鏂囦欢涓嶅瓨鍦�");
+ }
+
+ try {
+ // 妫�鏌ユ槸鍚︿负鍥剧墖鏂囦欢
+ String fileName = file.getName().toLowerCase();
+ boolean isImage = fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") ||
+ fileName.endsWith(".png") || fileName.endsWith(".gif");
+
+ // 涓婁紶鍘熸枃浠�
+ FileUploadResponse uploadResponse = uploadLocalFile(file, targetPath);
+ if (!uploadResponse.isSuccess()) {
+ return uploadResponse;
+ }
+
+ // 濡傛灉鏄浘鐗囷紝鐢熸垚缂╃暐鍥�
+ if (isImage && uploadResponse.getFilePath() != null) {
+ String originalPath = uploadResponse.getFilePath();
+ String thumbnailPath = generateThumbnailPath(originalPath);
+
+ // 鐢熸垚缂╃暐鍥�
+ if (createThumbnail(originalPath, thumbnailPath, 100, 0)) {
+ uploadResponse.setThumbnailPath(thumbnailPath);
+ log.info("缂╃暐鍥剧敓鎴愭垚鍔燂細{}", thumbnailPath);
+ } else {
+ log.warn("缂╃暐鍥剧敓鎴愬け璐ワ細{}", originalPath);
+ }
+ }
+
+ return uploadResponse;
+
+ } catch (Exception e) {
+ log.error("涓婁紶鏂囦欢骞剁敓鎴愮缉鐣ュ浘澶辫触锛歿}", file.getAbsolutePath(), e);
+ return FileUploadResponse.error("涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * MultipartFile涓婁紶锛堝寘鍚缉鐣ュ浘鐢熸垚锛�
+ */
+ public FileUploadResponse uploadMultipartFileWithThumbnail(MultipartFile multipartFile, String targetPath) {
+ if (multipartFile == null || multipartFile.isEmpty()) {
+ return FileUploadResponse.error("鏂囦欢涓虹┖");
+ }
+
+ try {
+ // 妫�鏌ユ槸鍚︿负鍥剧墖鏂囦欢
+ String originalFilename = multipartFile.getOriginalFilename();
+ if (originalFilename != null) {
+ String fileName = originalFilename.toLowerCase();
+ boolean isImage = fileName.endsWith(".jpg") || fileName.endsWith(".jpeg") ||
+ fileName.endsWith(".png") || fileName.endsWith(".gif");
+
+ // 涓婁紶鍘熸枃浠�
+ FileUploadResponse uploadResponse = uploadMultipartFile(multipartFile, targetPath);
+ if (!uploadResponse.isSuccess()) {
+ return uploadResponse;
+ }
+
+
+
+ return uploadResponse;
+ }
+
+ return uploadMultipartFile(multipartFile, targetPath);
+
+ } catch (Exception e) {
+ log.error("涓婁紶MultipartFile骞剁敓鎴愮缉鐣ュ浘澶辫触", e);
+ return FileUploadResponse.error("涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 鐢熸垚缂╃暐鍥捐矾寰�
+ */
+ private String generateThumbnailPath(String originalPath) {
+ if (originalPath == null || originalPath.isEmpty()) {
+ return null;
+ }
+
+ // 鍦ㄦ枃浠跺悕鍓嶆坊鍔� "s_" 鍓嶇紑
+ int lastSlashIndex = originalPath.lastIndexOf('/');
+ if (lastSlashIndex >= 0) {
+ String directory = originalPath.substring(0, lastSlashIndex + 1);
+ String fileName = originalPath.substring(lastSlashIndex + 1);
+ return directory + "s_" + fileName;
+ } else {
+ return "s_" + originalPath;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/file/IFileUploadService.java b/ruoyi-system/src/main/java/com/ruoyi/system/file/IFileUploadService.java
new file mode 100644
index 0000000..0e11986
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/file/IFileUploadService.java
@@ -0,0 +1,108 @@
+package com.ruoyi.system.file;
+
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.InputStream;
+
+public interface IFileUploadService {
+
+ /**
+ * 涓婁紶鏈湴鏂囦欢鍒癙HP鎺ュ彛
+ *
+ * @param file 瑕佷笂浼犵殑鏂囦欢
+ * @param targetPath 鐩爣璺緞锛堢浉瀵逛簬PHP涓婁紶鐩綍锛�
+ * @return 涓婁紶缁撴灉
+ */
+ FileUploadResponse uploadLocalFile(File file, String targetPath);
+
+ /**
+ * 涓婁紶MultipartFile鍒癙HP鎺ュ彛
+ *
+ * @param multipartFile 瑕佷笂浼犵殑鏂囦欢
+ * @param targetPath 鐩爣璺緞锛堢浉瀵逛簬PHP涓婁紶鐩綍锛�
+ * @return 涓婁紶缁撴灉
+ */
+ FileUploadResponse uploadMultipartFile(MultipartFile multipartFile, String targetPath);
+
+ /**
+ * 涓婁紶瀛楄妭鏁扮粍鍒癙HP鎺ュ彛
+ *
+ * @param fileBytes 鏂囦欢瀛楄妭鏁扮粍
+ * @param fileName 鏂囦欢鍚�
+ * @param targetPath 鐩爣璺緞锛堢浉瀵逛簬PHP涓婁紶鐩綍锛�
+ * @return 涓婁紶缁撴灉
+ */
+ FileUploadResponse uploadBytes(byte[] fileBytes, String fileName, String targetPath);
+
+ /**
+ * 涓婁紶杈撳叆娴佸埌PHP鎺ュ彛
+ *
+ * @param inputStream 鏂囦欢杈撳叆娴�
+ * @param fileName 鏂囦欢鍚�
+ * @param targetPath 鐩爣璺緞锛堢浉瀵逛簬PHP涓婁紶鐩綍锛�
+ * @return 涓婁紶缁撴灉
+ */
+ FileUploadResponse uploadInputStream(InputStream inputStream, String fileName, String targetPath);
+
+ /**
+ * 浠嶶RL涓嬭浇鏂囦欢骞朵笂浼犲埌PHP鎺ュ彛
+ *
+ * @param fileUrl 鏂囦欢URL
+ * @param targetPath 鐩爣璺緞锛堢浉瀵逛簬PHP涓婁紶鐩綍锛�
+ * @return 涓婁紶缁撴灉
+ */
+ FileUploadResponse uploadFromUrl(String fileUrl, String targetPath);
+
+ /**
+ * 浠庡井淇PI涓嬭浇鏂囦欢骞朵笂浼犲埌PHP鎺ュ彛
+ *
+ * @param accessToken 寰俊璁块棶浠ょ墝
+ * @param mediaId 寰俊濯掍綋ID
+ * @param targetPath 鐩爣璺緞锛堢浉瀵逛簬PHP涓婁紶鐩綍锛�
+ * @return 涓婁紶缁撴灉
+ */
+ FileUploadResponse uploadFromWechat(String accessToken, String mediaId, String targetPath);
+
+ /**
+ * 妫�鏌ユ枃浠舵槸鍚﹀瓨鍦�
+ *
+ * @param filePath 鏂囦欢璺緞
+ * @return 鏄惁瀛樺湪
+ */
+ boolean fileExists(String filePath);
+
+ /**
+ * 鍒犻櫎鏂囦欢
+ *
+ * @param filePath 鏂囦欢璺緞
+ * @return 鏄惁鍒犻櫎鎴愬姛
+ */
+ boolean deleteFile(String filePath);
+
+ /**
+ * 鑾峰彇鏂囦欢璁块棶URL
+ *
+ * @param filePath 鏂囦欢璺緞
+ * @return 璁块棶URL
+ */
+ String getFileUrl(String filePath);
+
+ /**
+ * 涓婁紶鏈湴鏂囦欢鍒癙HP鎺ュ彛锛堝寘鍚缉鐣ュ浘鐢熸垚锛�
+ *
+ * @param file 瑕佷笂浼犵殑鏂囦欢
+ * @param targetPath 鐩爣璺緞锛堢浉瀵逛簬PHP涓婁紶鐩綍锛�
+ * @return 涓婁紶缁撴灉
+ */
+ FileUploadResponse uploadLocalFileWithThumbnail(File file, String targetPath);
+
+ /**
+ * 涓婁紶MultipartFile鍒癙HP鎺ュ彛锛堝寘鍚缉鐣ュ浘鐢熸垚锛�
+ *
+ * @param multipartFile 瑕佷笂浼犵殑鏂囦欢
+ * @param targetPath 鐩爣璺緞锛堢浉瀵逛簬PHP涓婁紶鐩綍锛�
+ * @return 涓婁紶缁撴灉
+ */
+ FileUploadResponse uploadMultipartFileWithThumbnail(MultipartFile multipartFile, String targetPath);
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/IImageDataService.java b/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/IImageDataService.java
new file mode 100644
index 0000000..e2b48b3
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/IImageDataService.java
@@ -0,0 +1,200 @@
+package com.ruoyi.system.imagedata;
+
+
+import com.ruoyi.system.domain.ImageData;
+
+import java.util.List;
+
+/**
+ * 鍥剧墖鏁版嵁Service鎺ュ彛
+ */
+public interface IImageDataService {
+ /**
+ * 鏌ヨ鍥剧墖鏁版嵁
+ *
+ * @param id 鍥剧墖鏁版嵁涓婚敭
+ * @return 鍥剧墖鏁版嵁
+ */
+ public ImageData selectImageDataById(Long id);
+
+ /**
+ * 鏌ヨ鍥剧墖鏁版嵁鍒楄〃
+ *
+ * @param imageData 鍥剧墖鏁版嵁
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ public List<ImageData> selectImageDataList(ImageData imageData);
+
+ /**
+ * 鏂板鍥剧墖鏁版嵁
+ *
+ * @param imageData 鍥剧墖鏁版嵁
+ * @return 缁撴灉
+ */
+ public int insertImageData(ImageData imageData);
+
+ /**
+ * 淇敼鍥剧墖鏁版嵁
+ *
+ * @param imageData 鍥剧墖鏁版嵁
+ * @return 缁撴灉
+ */
+ public int updateImageData(ImageData imageData);
+
+ /**
+ * 鎵归噺鍒犻櫎鍥剧墖鏁版嵁
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鍥剧墖鏁版嵁涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteImageDataByIds(Long[] ids);
+
+ /**
+ * 鍒犻櫎鍥剧墖鏁版嵁淇℃伅
+ *
+ * @param id 鍥剧墖鏁版嵁涓婚敭
+ * @return 缁撴灉
+ */
+ public int deleteImageDataById(Long id);
+
+ /**
+ * 鏍规嵁璋冨害鍗旾D鏌ヨ鍥剧墖鏁版嵁
+ *
+ * @param dOrdIDDt 璋冨害鍗旾D
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ public List<ImageData> selectImageDataByDOrdIDDt(Long dOrdIDDt);
+
+ String generateCompatibleFilePath(Long dispatchOrdID, String mediaId, boolean isThumbnail);
+
+ String generateCompatibleUrl(Long dispatchOrdID, String mediaId, boolean isThumbnail);
+
+ /**
+ * 鏍规嵁鏈嶅姟鍗旾D鏌ヨ鍥剧墖鏁版嵁
+ *
+ * @param sOrdIDDt 鏈嶅姟鍗旾D
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ public List<ImageData> selectImageDataBySOrdIDDt(Long sOrdIDDt);
+
+ /**
+ * 鏍规嵁鍥剧墖绫诲瀷鏌ヨ鍥剧墖鏁版嵁
+ *
+ * @param imageType 鍥剧墖绫诲瀷
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ public List<ImageData> selectImageDataByType(Integer imageType);
+
+ /**
+ * 鏍囪鍥剧墖涓哄垹闄ょ姸鎬�
+ *
+ * @param id 鍥剧墖鏁版嵁涓婚敭
+ * @return 缁撴灉
+ */
+ public int markImageDataAsDeleted(Long id);
+
+ /**
+ * 寰俊鍥剧墖涓婁紶澶勭悊锛堝師ASP浠g爜杞崲锛�
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param serviceOrdID 鏈嶅姟鍗旾D
+ * @param oaid OA鐢ㄦ埛ID
+ * @param mediaId 寰俊濯掍綋ID
+ * @param imageType 鍥剧墖绫诲瀷
+ * @param adminId 褰撳墠绠$悊鍛業D
+ * @return 澶勭悊缁撴灉
+ */
+ public String uploadWxImage(Long dispatchOrdID, Long serviceOrdID, Integer oaid,
+ String mediaId, Integer imageType, Integer adminId);
+
+
+ /**
+ * 淇濆瓨寰俊鏂囦欢鍒版湰鍦帮紙鍘烶HP浠g爜杞崲锛�
+ *
+ * @param filename 鏂囦欢鍚�
+ * @param fileContent 鏂囦欢鍐呭
+ * @return 鏄惁淇濆瓨鎴愬姛
+ */
+ public boolean saveWeixinFile(String filename, byte[] fileContent);
+
+ /**
+ * 鐢熸垚缂╃暐鍥撅紙鍘烶HP浠g爜杞崲锛�
+ *
+ * @param bigImgPath 鍘熷澶у浘璺緞
+ * @param width 缂╃暐鍥惧搴�
+ * @param height 缂╃暐鍥鹃珮搴︼紙0琛ㄧず鎸夋瘮渚嬭绠楋級
+ * @param smallImgPath 缂╃暐鍥句繚瀛樿矾寰�
+ * @return 鏄惁鐢熸垚鎴愬姛
+ */
+ public boolean createThumbnail(String bigImgPath, int width, int height, String smallImgPath);
+
+
+
+ /**
+ * 妫�鏌ユ枃浠跺吋瀹规�э紙纭繚涓庢棫绯荤粺鍏煎锛�
+ *
+ * @param filePath 鏂囦欢璺緞
+ * @return 鍏煎鎬ф鏌ョ粨鏋�
+ */
+ public String checkFileCompatibility(String filePath);
+
+ /**
+ * 楠岃瘉URL鏍煎紡鏄惁涓庢棫绯荤粺鍏煎
+ *
+ * @param url 鍥剧墖URL
+ * @return 鏄惁鍏煎
+ */
+ public boolean isUrlCompatible(String url);
+
+
+
+ /**
+ * 閫氳繃鍥剧墖URL涓婁紶澶勭悊锛堝厑璁哥洿鎺ヤ紶鍏ュ浘鐗嘦RL锛�
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param serviceOrdID 鏈嶅姟鍗旾D
+ * @param oaid OA鐢ㄦ埛ID
+ * @param imageUrl 鍥剧墖URL
+ * @param thumbnailUrl 缂╃暐鍥綰RL锛堝彲閫夛級
+ * @param imageType 鍥剧墖绫诲瀷
+ * @param adminId 褰撳墠绠$悊鍛業D
+ * @return 澶勭悊缁撴灉
+ */
+ public String uploadImageByUrl(Long dispatchOrdID, Long serviceOrdID, Integer oaid,
+ String imageUrl, String thumbnailUrl, Integer imageType, Integer adminId);
+
+ /**
+ * 閫氳繃鍥剧墖URL涓婁紶澶勭悊锛堢畝鍖栫増鏈紝鑷姩鐢熸垚缂╃暐鍥綰RL锛�
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param serviceOrdID 鏈嶅姟鍗旾D
+ * @param oaid OA鐢ㄦ埛ID
+ * @param imageUrl 鍥剧墖URL
+ * @param imageType 鍥剧墖绫诲瀷
+ * @param adminId 褰撳墠绠$悊鍛業D
+ * @return 澶勭悊缁撴灉
+ */
+ public String uploadImageByUrlSimple(Long dispatchOrdID, Long serviceOrdID, Integer oaid,
+ String imageUrl, Integer imageType, Integer adminId);
+ /**
+ * 寰俊鍥剧墖涓婁紶澶勭悊锛堝畬鏁寸増鏈紝鍖呭惈鏂囦欢涓嬭浇鍜岀缉鐣ュ浘鐢熸垚锛�
+ *
+ * @param accessToken 寰俊璁块棶浠ょ墝
+ * @param mediaId 寰俊濯掍綋ID
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param oaid OA鐢ㄦ埛ID
+ * @param imageType 鍥剧墖绫诲瀷
+ * @param adminId 褰撳墠绠$悊鍛業D
+ * @return 澶勭悊缁撴灉
+ */
+ public String uploadWxImageWithDownload(String accessToken, String mediaId, Long dispatchOrdID,
+ Integer oaid, Integer imageType, Integer adminId);
+ /**
+ * 鏍规嵁璋冨害鍗旾D鍜屽浘鐗囩被鍨嬫煡璇㈠浘鐗囨暟鎹�
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param imageType 鍥剧墖绫诲瀷
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ public List<ImageData> selectImageDataByDOrdIDDtAndType(Long dispatchOrdID, Integer imageType);
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/ImageDataServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/ImageDataServiceImpl.java
new file mode 100644
index 0000000..f98fe8a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/ImageDataServiceImpl.java
@@ -0,0 +1,644 @@
+package com.ruoyi.system.imagedata;
+
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.config.LegacySystemConfig;
+import com.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.system.domain.ImageData;
+import com.ruoyi.system.domain.enums.ImageTypeEnum;
+import com.ruoyi.system.file.FileUploadResponse;
+import com.ruoyi.system.file.IFileUploadService;
+import com.ruoyi.system.mapper.ImageDataMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+
+@Service
+@DataSource(DataSourceType.SQLSERVER)
+public class ImageDataServiceImpl implements IImageDataService {
+
+ private static final Logger log = LoggerFactory.getLogger(ImageDataServiceImpl.class);
+ @Autowired
+ private ImageDataMapper imageDataMapper;
+
+ @Autowired
+ private IFileUploadService fileUploadService;
+
+ @Autowired
+ private LegacySystemConfig legacyConfig;
+ /**
+ * 鏌ヨ鍥剧墖鏁版嵁
+ *
+ * @param id 鍥剧墖鏁版嵁涓婚敭
+ * @return 鍥剧墖鏁版嵁
+ */
+ @Override
+ public ImageData selectImageDataById(Long id) {
+ return imageDataMapper.selectImageDataById(id);
+ }
+
+ /**
+ * 鏌ヨ鍥剧墖鏁版嵁鍒楄〃
+ *
+ * @param imageData 鍥剧墖鏁版嵁
+ * @return 鍥剧墖鏁版嵁
+ */
+ @Override
+ public List<ImageData> selectImageDataList(ImageData imageData) {
+ return imageDataMapper.selectImageDataList(imageData);
+ }
+
+ /**
+ * 鏂板鍥剧墖鏁版嵁
+ *
+ * @param imageData 鍥剧墖鏁版嵁
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertImageData(ImageData imageData) {
+ return imageDataMapper.insertImageData(imageData);
+ }
+
+ /**
+ * 淇敼鍥剧墖鏁版嵁
+ *
+ * @param imageData 鍥剧墖鏁版嵁
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateImageData(ImageData imageData) {
+ return imageDataMapper.updateImageData(imageData);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎鍥剧墖鏁版嵁
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鍥剧墖鏁版嵁涓婚敭
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteImageDataByIds(Long[] ids) {
+ return imageDataMapper.deleteImageDataByIds(ids);
+ }
+
+ /**
+ * 鍒犻櫎鍥剧墖鏁版嵁淇℃伅
+ *
+ * @param id 鍥剧墖鏁版嵁涓婚敭
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteImageDataById(Long id) {
+ return imageDataMapper.deleteImageDataById(id);
+ }
+
+ /**
+ * 鏍规嵁璋冨害鍗旾D鏌ヨ鍥剧墖鏁版嵁
+ *
+ * @param dOrdIDDt 璋冨害鍗旾D
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ @Override
+ public List<ImageData> selectImageDataByDOrdIDDt(Long dOrdIDDt) {
+ return imageDataMapper.selectImageDataByDOrdIDDt(dOrdIDDt);
+ }
+ /**
+ * 鐢熸垚涓庢棫绯荤粺鍏煎鐨勬枃浠惰矾寰�
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param mediaId 濯掍綋ID
+ * @param isThumbnail 鏄惁涓虹缉鐣ュ浘
+ * @return 鍏煎鐨勬枃浠惰矾寰�
+ */
+
+ @Override
+ public String generateCompatibleFilePath(Long dispatchOrdID, String mediaId, boolean isThumbnail) {
+ try {
+ String yearMonth = DateUtils.dateTimeNow("yyyyMM");
+ String fileName = dispatchOrdID + "_" + mediaId + ".jpg";
+
+ if (isThumbnail) {
+ fileName = "s_" + fileName;
+ }
+
+ return legacyConfig.getFileServerUrl() + "/" + yearMonth + "/" + fileName;
+ } catch (Exception e) {
+ log.error("鐢熸垚鍏煎鏂囦欢璺緞澶辫触锛歿}", e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * 鐢熸垚涓庢棫绯荤粺鍏煎鐨勮闂甎RL
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param mediaId 濯掍綋ID
+ * @param isThumbnail 鏄惁涓虹缉鐣ュ浘
+ * @return 鍏煎鐨勮闂甎RL
+ */
+ @Override
+ public String generateCompatibleUrl(Long dispatchOrdID, String mediaId, boolean isThumbnail) {
+ try {
+ String yearMonth = DateUtils.dateTimeNow("yyyyMM");
+ String fileName = dispatchOrdID + "_" + mediaId + ".jpg";
+
+ if (isThumbnail) {
+ fileName = "s_" + fileName;
+ }
+
+ return legacyConfig.getFileServerUrl() + "/" + yearMonth + "/" + fileName;
+ } catch (Exception e) {
+ log.error("鐢熸垚鍏煎URL澶辫触锛歿}", e.getMessage());
+ return null;
+ }
+ }
+ /**
+ * 鏍规嵁鏈嶅姟鍗旾D鏌ヨ鍥剧墖鏁版嵁
+ *
+ * @param sOrdIDDt 鏈嶅姟鍗旾D
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ @Override
+ public List<ImageData> selectImageDataBySOrdIDDt(Long sOrdIDDt) {
+ return imageDataMapper.selectImageDataBySOrdIDDt(sOrdIDDt);
+ }
+
+ /**
+ * 鏍规嵁鍥剧墖绫诲瀷鏌ヨ鍥剧墖鏁版嵁
+ *
+ * @param imageType 鍥剧墖绫诲瀷
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ @Override
+ public List<ImageData> selectImageDataByType(Integer imageType) {
+ ImageData imageData = new ImageData();
+ imageData.setImageType(imageType);
+ return imageDataMapper.selectImageDataList(imageData);
+ }
+
+ /**
+ * 鏍囪鍥剧墖涓哄垹闄ょ姸鎬�
+ *
+ * @param id 鍥剧墖鏁版嵁涓婚敭
+ * @return 缁撴灉
+ */
+ @Override
+ public int markImageDataAsDeleted(Long id) {
+ ImageData imageData = new ImageData();
+ imageData.setId(id);
+ imageData.setImageDel(1); // 1琛ㄧず宸插垹闄�
+ return imageDataMapper.updateImageData(imageData);
+ }
+
+
+ /**
+ * 寰俊鍥剧墖涓婁紶澶勭悊锛堝師ASP浠g爜杞崲锛�
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param serviceOrdID 鏈嶅姟鍗旾D
+ * @param oaid OA鐢ㄦ埛ID
+ * @param mediaId 寰俊濯掍綋ID
+ * @param imageType 鍥剧墖绫诲瀷
+ * @param adminId 褰撳墠绠$悊鍛業D
+ * @return 澶勭悊缁撴灉
+ */
+
+ public String uploadWxImage(Long dispatchOrdID, Long serviceOrdID, Integer oaid,
+ String mediaId, Integer imageType, Integer adminId) {
+ try {
+ // 鑾峰彇鍥剧墖绫诲瀷鏋氫妇
+ ImageTypeEnum imageTypeEnum = ImageTypeEnum.getByCode(imageType);
+
+ // 濡傛灉鏈夎皟搴﹀崟ID锛屽垯澶勭悊璋冨害鍗曠浉鍏冲浘鐗�
+ if (dispatchOrdID != null && dispatchOrdID > 0) {
+ return processDispatchOrderImage(dispatchOrdID, serviceOrdID, mediaId, imageTypeEnum, adminId);
+ }
+ // 濡傛灉鍙湁OA鐢ㄦ埛ID锛屽垯鏇存柊鐢ㄦ埛澶村儚
+ else if (oaid != null && oaid > 0) {
+ return updateUserAvatar(oaid, mediaId);
+ }
+ else {
+ return "鍙傛暟閿欒锛氱己灏戝繀瑕佺殑鍙傛暟";
+ }
+ } catch (Exception e) {
+ return "澶勭悊澶辫触锛�" + e.getMessage();
+ }
+ }
+
+ /**
+ * 澶勭悊璋冨害鍗曠浉鍏冲浘鐗囦笂浼�
+ */
+ private String processDispatchOrderImage(Long dispatchOrdID, Long serviceOrdID,
+ String mediaId, ImageTypeEnum imageTypeEnum, Integer adminId) {
+ try {
+ // 鐢熸垚鍥剧墖URL璺緞
+ String imageUrl = generateImageUrl(dispatchOrdID, mediaId, false);
+ String imageUrls = generateImageUrl(dispatchOrdID, mediaId, true);
+
+ // 鍒涘缓鍥剧墖鏁版嵁瀵硅薄
+ ImageData imageData = new ImageData();
+ imageData.setDOrdIDDt(dispatchOrdID);
+ imageData.setSOrdIDDt(serviceOrdID);
+ imageData.setImageType(imageTypeEnum.getCode());
+ imageData.setImageUrl(imageUrl);
+ imageData.setImageUrls(imageUrls);
+ imageData.setUpImageTime(new Date());
+ imageData.setUpImageOAid(adminId);
+ imageData.setImageDel(0); // 0琛ㄧず鏈垹闄�
+
+ // 鎻掑叆鍥剧墖鏁版嵁
+ int result = imageDataMapper.insertImageData(imageData);
+ if (result <= 0) {
+ return "鍥剧墖鏁版嵁淇濆瓨澶辫触";
+ }
+
+
+ return "鍥剧墖涓婁紶鎴愬姛锛孖D: " + imageData.getId() + "锛岀被鍨�: " + imageTypeEnum.getDescription();
+
+ } catch (Exception e) {
+ return "澶勭悊璋冨害鍗曞浘鐗囧け璐ワ細" + e.getMessage();
+ }
+ }
+
+ /**
+ * 鏇存柊鐢ㄦ埛澶村儚
+ */
+ private String updateUserAvatar(Integer oaid, String mediaId) {
+ try {
+ // 杩欓噷闇�瑕佽皟鐢∣A鐢ㄦ埛鏈嶅姟鏉ユ洿鏂板ご鍍�
+ // 鐢变簬娌℃湁OA鐢ㄦ埛鏈嶅姟鐨勫叿浣撳疄鐜帮紝杩欓噷鍙槸绀轰緥
+ String avatarUrl = "/upload/" + oaid + "_" + mediaId + ".jpg";
+
+ // TODO: 璋冪敤OA鐢ㄦ埛鏈嶅姟鏇存柊澶村儚
+ // oaUserService.updateAvatar(oaid, avatarUrl);
+
+ return "鐢ㄦ埛澶村儚鏇存柊鎴愬姛";
+ } catch (Exception e) {
+ return "鏇存柊鐢ㄦ埛澶村儚澶辫触锛�" + e.getMessage();
+ }
+ }
+
+ /**
+ * 鐢熸垚鍥剧墖URL
+ */
+ private String generateImageUrl(Long dispatchOrdID, String mediaId, boolean isThumbnail) {
+ Date now = new Date();
+ int year = now.getYear() + 1900; // Java鐨勫勾浠介渶瑕佸姞1900
+ int month = now.getMonth() + 1; // Java鐨勬湀浠戒粠0寮�濮�
+
+ String monthStr = String.format("%02d", month);
+ String prefix = isThumbnail ? "/upload/" + year + monthStr + "/s_" : "/upload/" + year + monthStr + "/";
+
+ return prefix + dispatchOrdID + "_" + mediaId + ".jpg";
+ }
+
+
+
+
+ /**
+ * 淇濆瓨寰俊鏂囦欢鍒版湰鍦帮紙鍘烶HP浠g爜杞崲锛�
+ *
+ * @param filename 鏂囦欢鍚�
+ * @param fileContent 鏂囦欢鍐呭
+ * @return 鏄惁淇濆瓨鎴愬姛
+ */
+ public boolean saveWeixinFile(String filename, byte[] fileContent) {
+ FileOutputStream localFile = null;
+ try {
+ // 纭繚鐩綍瀛樺湪
+ File file = new File(filename);
+ File parentDir = file.getParentFile();
+ if (!parentDir.exists()) {
+ parentDir.mkdirs();
+ }
+
+ localFile = new FileOutputStream(filename);
+ localFile.write(fileContent);
+ localFile.flush();
+
+ log.info("鎴愬姛淇濆瓨寰俊鏂囦欢锛歿}", filename);
+ return true;
+ } catch (Exception e) {
+ log.error("淇濆瓨寰俊鏂囦欢澶辫触锛歿}", e.getMessage(), e);
+ return false;
+ } finally {
+ if (localFile != null) {
+ try {
+ localFile.close();
+ } catch (IOException e) {
+ log.error("鍏抽棴鏂囦欢娴佸け璐ワ細{}", e.getMessage());
+ }
+ }
+ }
+ }
+
+ /**
+ * 鐢熸垚缂╃暐鍥撅紙鍘烶HP浠g爜杞崲锛�
+ *
+ * @param bigImgPath 鍘熷澶у浘璺緞
+ * @param width 缂╃暐鍥惧搴�
+ * @param height 缂╃暐鍥鹃珮搴︼紙0琛ㄧず鎸夋瘮渚嬭绠楋級
+ * @param smallImgPath 缂╃暐鍥句繚瀛樿矾寰�
+ * @return 鏄惁鐢熸垚鎴愬姛
+ */
+ public boolean createThumbnail(String bigImgPath, int width, int height, String smallImgPath) {
+ try {
+ // 璇诲彇鍘熷鍥剧墖
+ BufferedImage originalImage = ImageIO.read(new File(bigImgPath));
+ if (originalImage == null) {
+ log.error("鏃犳硶璇诲彇鍘熷鍥剧墖锛歿}", bigImgPath);
+ return false;
+ }
+
+ int srcWidth = originalImage.getWidth();
+ int srcHeight = originalImage.getHeight();
+
+ // 璁$畻缂╃暐鍥惧昂瀵�
+ if (height == 0) {
+ height = (int) Math.floor((double) width / srcWidth * srcHeight);
+ } else if (width == 0) {
+ width = (int) Math.floor((double) height / srcHeight * srcWidth);
+ }
+
+ // 鍒涘缓缂╃暐鍥�
+ BufferedImage thumbnail = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ Graphics2D g = thumbnail.createGraphics();
+
+ // 璁剧疆娓叉煋璐ㄩ噺
+ g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+ g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ // 缁樺埗缂╃暐鍥�
+ g.drawImage(originalImage, 0, 0, width, height, null);
+ g.dispose();
+
+ // 纭繚鐩綍瀛樺湪
+ File smallImgFile = new File(smallImgPath);
+ File parentDir = smallImgFile.getParentFile();
+ if (!parentDir.exists()) {
+ parentDir.mkdirs();
+ }
+
+ // 淇濆瓨缂╃暐鍥�
+ ImageIO.write(thumbnail, "jpg", smallImgFile);
+
+ log.info("鎴愬姛鐢熸垚缂╃暐鍥撅細{} -> {} ({}x{})", bigImgPath, smallImgPath, width, height);
+ return true;
+ } catch (Exception e) {
+ log.error("鐢熸垚缂╃暐鍥惧け璐ワ細{}", e.getMessage(), e);
+ return false;
+ }
+ }
+
+
+ /**
+ * 澶勭悊璋冨害鍗曠浉鍏冲浘鐗囦笂浼狅紙鍖呭惈鏂囦欢URL锛�
+ */
+ private String processDispatchOrderImageWithFiles(Long dispatchOrdID, Long serviceOrdID,
+ String mediaId, ImageTypeEnum imageTypeEnum,
+ Integer adminId, String originalImageUrl, String thumbnailUrl) {
+ try {
+ // 鍒涘缓鍥剧墖鏁版嵁瀵硅薄
+ ImageData imageData = new ImageData();
+ imageData.setDOrdIDDt(dispatchOrdID);
+ imageData.setSOrdIDDt(serviceOrdID);
+ imageData.setImageType(imageTypeEnum.getCode());
+ imageData.setImageUrl(originalImageUrl);
+ imageData.setImageUrls(thumbnailUrl);
+ imageData.setUpImageTime(new Date());
+ imageData.setUpImageOAid(adminId);
+ imageData.setImageDel(0); // 0琛ㄧず鏈垹闄�
+
+ // 鎻掑叆鍥剧墖鏁版嵁
+ int result = imageDataMapper.insertImageData(imageData);
+ if (result <= 0) {
+ return "鍥剧墖鏁版嵁淇濆瓨澶辫触";
+ }
+
+
+ return "鍥剧墖涓婁紶鎴愬姛锛孖D: " + imageData.getId() + "锛岀被鍨�: " + imageTypeEnum.getDescription() +
+ "锛屽師濮嬪浘鐗嘦RL: " + originalImageUrl + "锛岀缉鐣ュ浘URL: " + thumbnailUrl;
+
+ } catch (Exception e) {
+ return "澶勭悊璋冨害鍗曞浘鐗囧け璐ワ細" + e.getMessage();
+ }
+ }
+
+ /**
+ * 鏇存柊鐢ㄦ埛澶村儚锛堝寘鍚枃浠禪RL锛�
+ */
+ private String updateUserAvatarWithFile(Integer oaid, String mediaId, String imageUrl) {
+ try {
+ // 杩欓噷闇�瑕佽皟鐢∣A鐢ㄦ埛鏈嶅姟鏉ユ洿鏂板ご鍍�
+ // TODO: 璋冪敤OA鐢ㄦ埛鏈嶅姟鏇存柊澶村儚
+ // oaUserService.updateAvatar(oaid, imageUrl);
+
+ return "鐢ㄦ埛澶村儚鏇存柊鎴愬姛锛孶RL锛�" + imageUrl;
+ } catch (Exception e) {
+ return "鏇存柊鐢ㄦ埛澶村儚澶辫触锛�" + e.getMessage();
+ }
+ }
+
+ /**
+ * 妫�鏌ユ枃浠跺吋瀹规�э紙纭繚涓庢棫绯荤粺鍏煎锛�
+ *
+ * @param filePath 鏂囦欢璺緞
+ * @return 鍏煎鎬ф鏌ョ粨鏋�
+ */
+ public String checkFileCompatibility(String filePath) {
+ try {
+ File file = new File(filePath);
+
+ if (!file.exists()) {
+ return "鏂囦欢涓嶅瓨鍦細" + filePath;
+ }
+
+ // 妫�鏌ユ枃浠跺懡鍚嶆槸鍚︾鍚堟棫绯荤粺瑙勮寖
+ String fileName = file.getName();
+ if (!fileName.matches("^(\\d+|[A-Z]+)_[A-Za-z0-9_]+\\.jpg$")) {
+ return "鏂囦欢鍛藉悕涓嶇鍚堟棫绯荤粺瑙勮寖锛�" + fileName;
+ }
+
+ // 妫�鏌ョ洰褰曠粨鏋勬槸鍚︾鍚堟棫绯荤粺瑙勮寖
+ String parentDir = file.getParentFile().getName();
+ if (!parentDir.matches("^\\d{6}$")) { // 骞存湀鏍煎紡锛�202412
+ return "鐩綍缁撴瀯涓嶇鍚堟棫绯荤粺瑙勮寖锛�" + parentDir;
+ }
+
+ return "鏂囦欢鍏煎鎬ф鏌ラ�氳繃锛�" + filePath;
+ } catch (Exception e) {
+ return "鍏煎鎬ф鏌ュけ璐ワ細" + e.getMessage();
+ }
+ }
+
+ /**
+ * 楠岃瘉URL鏍煎紡鏄惁涓庢棫绯荤粺鍏煎
+ *
+ * @param url 鍥剧墖URL
+ * @return 鏄惁鍏煎
+ */
+ public boolean isUrlCompatible(String url) {
+ try {
+ // 妫�鏌RL鏍煎紡鏄惁绗﹀悎鏃х郴缁熻鑼�
+ // 鏃х郴缁熸牸寮忥細/upload/骞存湀/鏂囦欢鍚�.jpg
+ return url.matches("^/upload/\\d{6}/[A-Za-z0-9_]+\\.jpg$");
+ } catch (Exception e) {
+ log.error("URL鍏煎鎬ф鏌ュけ璐ワ細{}", e.getMessage());
+ return false;
+ }
+ }
+
+
+
+ /**
+ * 閫氳繃鍥剧墖URL涓婁紶澶勭悊锛堝厑璁哥洿鎺ヤ紶鍏ュ浘鐗嘦RL锛�
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param serviceOrdID 鏈嶅姟鍗旾D
+ * @param oaid OA鐢ㄦ埛ID
+ * @param imageUrl 鍥剧墖URL
+ * @param thumbnailUrl 缂╃暐鍥綰RL锛堝彲閫夛級
+ * @param imageType 鍥剧墖绫诲瀷
+ * @param adminId 褰撳墠绠$悊鍛業D
+ * @return 澶勭悊缁撴灉
+ */
+ @Override
+
+ public String uploadImageByUrl(Long dispatchOrdID, Long serviceOrdID, Integer oaid,
+ String imageUrl, String thumbnailUrl, Integer imageType, Integer adminId) {
+ try {
+ // 楠岃瘉鍙傛暟
+ if (imageUrl == null || imageUrl.trim().isEmpty()) {
+ return "鍥剧墖URL涓嶈兘涓虹┖";
+ }
+
+ // 澶勭悊涓氬姟閫昏緫
+ if (dispatchOrdID != null && dispatchOrdID > 0) {
+ // 璋冨害鍗曠浉鍏冲浘鐗�
+ ImageTypeEnum imageTypeEnum = ImageTypeEnum.getByCode(imageType);
+ return processDispatchOrderImageWithFiles(dispatchOrdID, serviceOrdID, null,
+ imageTypeEnum, adminId, imageUrl, thumbnailUrl);
+ } else if (oaid != null && oaid > 0) {
+ // OA鐢ㄦ埛澶村儚
+ return updateUserAvatarWithFile(oaid, null, imageUrl);
+ } else {
+ return "鍙傛暟閿欒锛氱己灏戝繀瑕佺殑鍙傛暟锛堣皟搴﹀崟ID鎴朞A鐢ㄦ埛ID锛�";
+ }
+ } catch (Exception e) {
+ log.error("閫氳繃URL涓婁紶鍥剧墖澶辫触锛歿}", e.getMessage(), e);
+ return "澶勭悊澶辫触锛�" + e.getMessage();
+ }
+ }
+
+ /**
+ * 閫氳繃鍥剧墖URL涓婁紶澶勭悊锛堢畝鍖栫増鏈紝鑷姩鐢熸垚缂╃暐鍥綰RL锛�
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param serviceOrdID 鏈嶅姟鍗旾D
+ * @param oaid OA鐢ㄦ埛ID
+ * @param imageUrl 鍥剧墖URL
+ * @param imageType 鍥剧墖绫诲瀷
+ * @param adminId 褰撳墠绠$悊鍛業D
+ * @return 澶勭悊缁撴灉
+ */
+ @Override
+
+ public String uploadImageByUrlSimple(Long dispatchOrdID, Long serviceOrdID, Integer oaid,
+ String imageUrl, Integer imageType, Integer adminId) {
+ try {
+ // 楠岃瘉鍙傛暟
+ if (imageUrl == null || imageUrl.trim().isEmpty()) {
+ return "鍥剧墖URL涓嶈兘涓虹┖";
+ }
+
+ // 鑷姩鐢熸垚缂╃暐鍥綰RL锛堝鏋滃師鍥綰RL鍖呭惈鏂囦欢鍚嶏級
+ String thumbnailUrl = null;
+ if (imageUrl.contains("/")) {
+ String fileName = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
+ if (fileName.contains(".")) {
+ String nameWithoutExt = fileName.substring(0, fileName.lastIndexOf("."));
+ String extension = fileName.substring(fileName.lastIndexOf("."));
+ String thumbnailFileName = "s_" + nameWithoutExt + extension;
+ thumbnailUrl = imageUrl.substring(0, imageUrl.lastIndexOf("/") + 1) + thumbnailFileName;
+ }
+ }
+
+ // 璋冪敤瀹屾暣鐗堟湰鐨勬柟娉�
+ return uploadImageByUrl(dispatchOrdID, serviceOrdID, oaid, imageUrl, thumbnailUrl, imageType, adminId);
+ } catch (Exception e) {
+ log.error("閫氳繃URL涓婁紶鍥剧墖锛堢畝鍖栫増锛夊け璐ワ細{}", e.getMessage(), e);
+ return "澶勭悊澶辫触锛�" + e.getMessage();
+ }
+ }
+
+ @Override
+ public String uploadWxImageWithDownload(String accessToken, String mediaId, Long dispatchOrdID, Integer oaid, Integer imageType, Integer adminId) {
+ try {
+ // 纭畾鐩爣璺緞
+ String targetPath;
+ if (dispatchOrdID != null && dispatchOrdID > 0) {
+ // 璋冨害鍗曠浉鍏冲浘鐗囷細鎸夊勾鏈堢粍缁囩洰褰�
+ String yearMonth = DateUtils.dateTimeNow("yyyyMM");
+ targetPath = yearMonth + "/" + dispatchOrdID;
+ } else if (oaid != null && oaid > 0) {
+ // OA鐢ㄦ埛澶村儚
+ targetPath = "avatar/" + oaid;
+ } else {
+ return "鍙傛暟閿欒锛氱己灏戝繀瑕佺殑鍙傛暟";
+ }
+
+ // 浣跨敤鏂囦欢涓婁紶鏈嶅姟浠庡井淇′笅杞藉苟涓婁紶鏂囦欢
+ FileUploadResponse uploadResponse = fileUploadService.uploadFromWechat(accessToken, mediaId, targetPath);
+ if (!uploadResponse.isSuccess()) {
+ return "鏂囦欢涓婁紶澶辫触锛�" + uploadResponse.getMessage();
+ }
+
+ // 鑾峰彇涓婁紶鍚庣殑鏂囦欢璺緞
+ String originalImageUrl = uploadResponse.getFilePath();
+ String thumbnailUrl = uploadResponse.getThumbnailPath();
+
+ // 澶勭悊涓氬姟閫昏緫
+ if (dispatchOrdID != null && dispatchOrdID > 0) {
+ return processDispatchOrderImageWithFiles(dispatchOrdID, null, mediaId,
+ ImageTypeEnum.getByCode(imageType), adminId, originalImageUrl, thumbnailUrl);
+ } else if (oaid != null && oaid > 0) {
+ return updateUserAvatarWithFile(oaid, mediaId, originalImageUrl);
+ }
+
+ return "鍥剧墖涓婁紶鎴愬姛锛屾枃浠惰矾寰勶細" + originalImageUrl;
+ } catch (Exception e) {
+ log.error("寰俊鍥剧墖涓婁紶澶勭悊澶辫触锛歿}", e.getMessage(), e);
+ return "澶勭悊澶辫触锛�" + e.getMessage();
+ }
+ }
+
+ /**
+ * 鏍规嵁璋冨害鍗旾D鍜屽浘鐗囩被鍨嬫煡璇㈠浘鐗囨暟鎹�
+ *
+ * @param dispatchOrdID 璋冨害鍗旾D
+ * @param imageType 鍥剧墖绫诲瀷
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ @Override
+ public List<ImageData> selectImageDataByDOrdIDDtAndType(Long dispatchOrdID, Integer imageType) {
+ // 鍒涘缓鏌ヨ鏉′欢
+ ImageData imageData = new ImageData();
+ imageData.setDOrdIDDt(dispatchOrdID);
+ imageData.setImageType(imageType);
+
+ // 鏌ヨ鍥剧墖鏁版嵁
+ return imageDataMapper.selectImageDataList(imageData);
+ }
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/WxImageUploadRequest.java b/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/WxImageUploadRequest.java
new file mode 100644
index 0000000..41da5e1
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/imagedata/WxImageUploadRequest.java
@@ -0,0 +1,30 @@
+package com.ruoyi.system.imagedata;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+/**
+ * 寰俊鍥剧墖涓婁紶璇锋眰DTO
+ */
+@Data
+public class WxImageUploadRequest {
+
+ @JsonProperty("access_token")
+ private String accessToken;
+
+ @JsonProperty("DispatchOrdID")
+ private Long dispatchOrdID;
+
+ @JsonProperty("ServiceOrdID")
+ private Long serviceOrdID;
+
+ @JsonProperty("OAID")
+ private Integer oaid;
+
+ @JsonProperty("media_id")
+ private String mediaId;
+
+ @JsonProperty("ImageType")
+ private Integer imageType;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ImageDataMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ImageDataMapper.java
new file mode 100644
index 0000000..b973de9
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/ImageDataMapper.java
@@ -0,0 +1,78 @@
+package com.ruoyi.system.mapper;
+
+
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.system.domain.ImageData;
+
+import java.util.List;
+
+/**
+ * 鍥剧墖鏁版嵁Mapper鎺ュ彛
+ */
+@DataSource(DataSourceType.SQLSERVER)
+public interface ImageDataMapper {
+ /**
+ * 鏌ヨ鍥剧墖鏁版嵁
+ *
+ * @param id 鍥剧墖鏁版嵁涓婚敭
+ * @return 鍥剧墖鏁版嵁
+ */
+ public ImageData selectImageDataById(Long id);
+
+ /**
+ * 鏌ヨ鍥剧墖鏁版嵁鍒楄〃
+ *
+ * @param imageData 鍥剧墖鏁版嵁
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ public List<ImageData> selectImageDataList(ImageData imageData);
+
+ /**
+ * 鏂板鍥剧墖鏁版嵁
+ *
+ * @param imageData 鍥剧墖鏁版嵁
+ * @return 缁撴灉
+ */
+ public int insertImageData(ImageData imageData);
+
+ /**
+ * 淇敼鍥剧墖鏁版嵁
+ *
+ * @param imageData 鍥剧墖鏁版嵁
+ * @return 缁撴灉
+ */
+ public int updateImageData(ImageData imageData);
+
+ /**
+ * 鍒犻櫎鍥剧墖鏁版嵁
+ *
+ * @param id 鍥剧墖鏁版嵁涓婚敭
+ * @return 缁撴灉
+ */
+ public int deleteImageDataById(Long id);
+
+ /**
+ * 鎵归噺鍒犻櫎鍥剧墖鏁版嵁
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int deleteImageDataByIds(Long[] ids);
+
+ /**
+ * 鏍规嵁璋冨害鍗旾D鏌ヨ鍥剧墖鏁版嵁
+ *
+ * @param dOrdIDDt 璋冨害鍗旾D
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ public List<ImageData> selectImageDataByDOrdIDDt(Long dOrdIDDt);
+
+ /**
+ * 鏍规嵁鏈嶅姟鍗旾D鏌ヨ鍥剧墖鏁版嵁
+ *
+ * @param sOrdIDDt 鏈嶅姟鍗旾D
+ * @return 鍥剧墖鏁版嵁闆嗗悎
+ */
+ public List<ImageData> selectImageDataBySOrdIDDt(Long sOrdIDDt);
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java
index 362d630..de3a1c3 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTaskService.java
@@ -96,9 +96,21 @@
*
* @param taskId 浠诲姟ID
* @param file 鏂囦欢
+ * @param category 闄勪欢鍒嗙被
* @return 缁撴灉
*/
- public int uploadAttachment(Long taskId, MultipartFile file);
+ public int uploadAttachment(Long taskId, MultipartFile file, String category);
+
+ /**
+ * 浠庡井淇ediaId涓婁紶浠诲姟闄勪欢
+ *
+ * @param taskId 浠诲姟ID
+ * @param accessToken 寰俊AccessToken
+ * @param mediaId 寰俊mediaId
+ * @param category 闄勪欢鍒嗙被
+ * @return 缁撴灉
+ */
+ public int uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category);
/**
* 鍒犻櫎浠诲姟闄勪欢
@@ -107,6 +119,14 @@
* @return 缁撴灉
*/
public int deleteAttachment(Long attachmentId);
+
+ /**
+ * 鏍规嵁ID鑾峰彇闄勪欢璇︽儏
+ *
+ * @param attachmentId 闄勪欢ID
+ * @return 闄勪欢璇︽儏
+ */
+ public SysTaskAttachment getAttachmentById(Long attachmentId);
/**
* 鍒嗛厤杞﹁締缁欎换鍔�
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
index ac521d2..56a2244 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTaskServiceImpl.java
@@ -6,7 +6,11 @@
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
import com.ruoyi.system.utils.TaskCodeGenerator;
import org.springframework.beans.factory.annotation.Autowired;
@@ -496,11 +500,12 @@
*
* @param taskId 浠诲姟ID
* @param file 鏂囦欢
+ * @param category 闄勪欢鍒嗙被
* @return 缁撴灉
*/
@Override
@Transactional
- public int uploadAttachment(Long taskId, MultipartFile file) {
+ public int uploadAttachment(Long taskId, MultipartFile file, String category) {
try {
// 涓婁紶鏂囦欢
String fileName = FileUploadUtils.upload("/task", file);
@@ -512,6 +517,7 @@
attachment.setFilePath(filePath);
attachment.setFileSize(file.getSize());
attachment.setFileType(getFileType(file.getOriginalFilename()));
+ attachment.setAttachmentCategory(category);
attachment.setUploadTime(DateUtils.getNowDate());
attachment.setUploadBy(SecurityUtils.getUsername());
@@ -519,14 +525,112 @@
// 璁板綍鎿嶄綔鏃ュ織
if (result > 0) {
+ String categoryDesc = getCategoryDesc(category);
recordTaskLog(taskId, "UPDATE", "涓婁紶闄勪欢", null,
- "涓婁紶鏂囦欢锛�" + file.getOriginalFilename(),
+ "涓婁紶鏂囦欢锛�" + file.getOriginalFilename() + "(鍒嗙被锛�" + categoryDesc + ")",
SecurityUtils.getUserId(), SecurityUtils.getUsername());
}
return result;
} catch (IOException e) {
throw new RuntimeException("鏂囦欢涓婁紶澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 浠庡井淇ediaId涓婁紶浠诲姟闄勪欢
+ *
+ * @param taskId 浠诲姟ID
+ * @param accessToken 寰俊AccessToken
+ * @param mediaId 寰俊mediaId
+ * @param category 闄勪欢鍒嗙被
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int uploadAttachmentFromWechat(Long taskId, String accessToken, String mediaId, String category) {
+ try {
+ // 浠庡井淇℃湇鍔″櫒涓嬭浇鏂囦欢
+ String wechatUrl = String.format(
+ "https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s",
+ accessToken, mediaId
+ );
+
+ byte[] fileBytes = downloadFromUrl(wechatUrl);
+ if (fileBytes == null || fileBytes.length == 0) {
+ throw new RuntimeException("浠庡井淇′笅杞芥枃浠跺け璐�");
+ }
+
+ // 鐢熸垚鏂囦欢鍚嶏紙浣跨敤mediaId浣滀负鏂囦欢鍚嶇殑涓�閮ㄥ垎锛�
+ String fileName = "wx_" + mediaId.substring(0, Math.min(20, mediaId.length())) + "_" + System.currentTimeMillis() + ".jpg";
+
+ // 淇濆瓨鍒版湰鍦�
+ String baseDir = FileUploadUtils.getDefaultBaseDir();
+ String datePath = DateUtils.datePath();
+ String uploadDir = baseDir + "/task/" + datePath;
+
+ // 鍒涘缓鐩綍
+ File uploadPath = new File(uploadDir);
+ if (!uploadPath.exists()) {
+ uploadPath.mkdirs();
+ }
+
+ // 淇濆瓨鏂囦欢
+ String filePath = uploadDir + "/" + fileName;
+ File file = new File(filePath);
+ try (FileOutputStream fos = new FileOutputStream(file)) {
+ fos.write(fileBytes);
+ }
+
+ // 淇濆瓨闄勪欢璁板綍
+ SysTaskAttachment attachment = new SysTaskAttachment();
+ attachment.setTaskId(taskId);
+ attachment.setFileName(fileName);
+ attachment.setFilePath(filePath);
+ attachment.setFileSize((long) fileBytes.length);
+ attachment.setFileType("jpg");
+ attachment.setAttachmentCategory(category);
+ attachment.setUploadTime(DateUtils.getNowDate());
+ attachment.setUploadBy(SecurityUtils.getUsername());
+
+ int result = sysTaskAttachmentMapper.insertSysTaskAttachment(attachment);
+
+ // 璁板綍鎿嶄綔鏃ュ織
+ if (result > 0) {
+ String categoryDesc = getCategoryDesc(category);
+ recordTaskLog(taskId, "UPDATE", "涓婁紶闄勪欢", null,
+ "閫氳繃寰俊涓婁紶鏂囦欢锛�" + fileName + "(鍒嗙被锛�" + categoryDesc + ")",
+ SecurityUtils.getUserId(), SecurityUtils.getUsername());
+ }
+
+ return result;
+ } catch (Exception e) {
+ throw new RuntimeException("浠庡井淇′笂浼犳枃浠跺け璐ワ細" + e.getMessage());
+ }
+ }
+
+ /**
+ * 浠� URL 涓嬭浇鏂囦欢
+ */
+ private byte[] downloadFromUrl(String fileUrl) throws IOException {
+ URL url = new URL(fileUrl);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("GET");
+ connection.setConnectTimeout(10000);
+ connection.setReadTimeout(30000);
+
+ try (InputStream inputStream = connection.getInputStream()) {
+ byte[] buffer = new byte[4096];
+ int bytesRead;
+ java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
+
+ while ((bytesRead = inputStream.read(buffer)) != -1) {
+ outputStream.write(buffer, 0, bytesRead);
+ }
+
+ return outputStream.toByteArray();
+ } finally {
+ connection.disconnect();
}
}
@@ -561,6 +665,17 @@
}
return result;
+ }
+
+ /**
+ * 鏍规嵁ID鑾峰彇闄勪欢璇︽儏
+ *
+ * @param attachmentId 闄勪欢ID
+ * @return 闄勪欢璇︽儏
+ */
+ @Override
+ public SysTaskAttachment getAttachmentById(Long attachmentId) {
+ return sysTaskAttachmentMapper.selectSysTaskAttachmentByAttachmentId(attachmentId);
}
/**
@@ -1055,4 +1170,25 @@
sysTaskWelfareMapper.insertSysTaskWelfare(welfareInfo);
}
+
+ /**
+ * 鑾峰彇闄勪欢鍒嗙被鎻忚堪
+ *
+ * @param category 闄勪欢鍒嗙被浠g爜
+ * @return 鍒嗙被鎻忚堪
+ */
+ private String getCategoryDesc(String category) {
+ if (category == null || category.isEmpty()) {
+ return "鏈垎绫�";
+ }
+ switch (category) {
+ case "1": return "鐭ユ儏鍚屾剰涔�";
+ case "2": return "鐥呬汉璧勬枡";
+ case "3": return "鎿嶄綔璁板綍";
+ case "4": return "鍑鸿溅鍓�";
+ case "5": return "鍑鸿溅鍚�";
+ case "6": return "绯诲畨鍏ㄥ甫";
+ default: return "鍏朵粬";
+ }
+ }
}
diff --git a/ruoyi-system/src/main/resources/mapper/system/ImageDataMapper.xml b/ruoyi-system/src/main/resources/mapper/system/ImageDataMapper.xml
new file mode 100644
index 0000000..a810574
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/ImageDataMapper.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.ImageDataMapper">
+
+ <resultMap type="ImageData" id="ImageDataResult">
+ <result property="id" column="id"/>
+ <result property="dOrdIDDt" column="DOrdIDDt"/>
+ <result property="sOrdIDDt" column="SOrdIDDt"/>
+ <result property="imageType" column="ImageType"/>
+ <result property="imageUrl" column="ImageUrl"/>
+ <result property="imageUrls" column="ImageUrls"/>
+ <result property="imageDeg" column="ImageDeg"/>
+ <result property="upImageTime" column="UpImageTime"/>
+ <result property="upImageOAid" column="UpImageOAid"/>
+ <result property="imageDel" column="ImageDel"/>
+ <result property="isAP" column="isAP"/>
+ <result property="isAP_ID" column="isAP_ID"/>
+ <result property="isAP_Time" column="isAP_Time"/>
+ </resultMap>
+
+ <sql id="selectImageDataVo">
+ select id, DOrdIDDt, SOrdIDDt, ImageType, ImageUrl, ImageUrls, ImageDeg, UpImageTime, UpImageOAid, ImageDel, isAP, isAP_ID, isAP_Time
+ from ImageData
+ </sql>
+
+ <select id="selectImageDataList" parameterType="ImageData" resultMap="ImageDataResult">
+ <include refid="selectImageDataVo"/>
+ <where>
+ <if test="dOrdIDDt != null "> and DOrdIDDt = #{dOrdIDDt}</if>
+ <if test="sOrdIDDt != null "> and SOrdIDDt = #{sOrdIDDt}</if>
+ <if test="imageType != null "> and ImageType = #{imageType}</if>
+ <if test="imageUrl != null and imageUrl != ''"> and ImageUrl like concat('%', #{imageUrl}, '%')</if>
+ <if test="imageUrls != null and imageUrls != ''"> and ImageUrls like concat('%', #{imageUrls}, '%')</if>
+ <if test="imageDeg != null "> and ImageDeg = #{imageDeg}</if>
+ <if test="upImageTime != null "> and UpImageTime = #{upImageTime}</if>
+ <if test="upImageOAid != null "> and UpImageOAid = #{upImageOAid}</if>
+ <if test="imageDel != null "> and ImageDel = #{imageDel}</if>
+ <if test="isAP != null "> and isAP = #{isAP}</if>
+ <if test="isAP_ID != null "> and isAP_ID = #{isAP_ID}</if>
+ <if test="isAP_Time != null "> and isAP_Time = #{isAP_Time}</if>
+ </where>
+ </select>
+
+ <select id="selectImageDataById" parameterType="Long" resultMap="ImageDataResult">
+ <include refid="selectImageDataVo"/>
+ where id = #{id}
+ </select>
+
+ <select id="selectImageDataByDOrdIDDt" parameterType="Long" resultMap="ImageDataResult">
+ <include refid="selectImageDataVo"/>
+ where DOrdIDDt = #{dOrdIDDt}
+ </select>
+
+ <select id="selectImageDataBySOrdIDDt" parameterType="Long" resultMap="ImageDataResult">
+ <include refid="selectImageDataVo"/>
+ where SOrdIDDt = #{sOrdIDDt}
+ </select>
+
+ <insert id="insertImageData" parameterType="ImageData" useGeneratedKeys="true" keyProperty="id">
+ insert into ImageData
+ <trim prefix="(" suffix=")" suffixOverrides=",">
+ <if test="dOrdIDDt != null">DOrdIDDt,</if>
+ <if test="sOrdIDDt != null">SOrdIDDt,</if>
+ <if test="imageType != null">ImageType,</if>
+ <if test="imageUrl != null">ImageUrl,</if>
+ <if test="imageUrls != null">ImageUrls,</if>
+ <if test="imageDeg != null">ImageDeg,</if>
+ <if test="upImageTime != null">UpImageTime,</if>
+ <if test="upImageOAid != null">UpImageOAid,</if>
+ <if test="imageDel != null">ImageDel,</if>
+ <if test="isAP != null">isAP,</if>
+ <if test="isAP_ID != null">isAP_ID,</if>
+ <if test="isAP_Time != null">isAP_Time,</if>
+ </trim>
+ <trim prefix="values (" suffix=")" suffixOverrides=",">
+ <if test="dOrdIDDt != null">#{dOrdIDDt},</if>
+ <if test="sOrdIDDt != null">#{sOrdIDDt},</if>
+ <if test="imageType != null">#{imageType},</if>
+ <if test="imageUrl != null">#{imageUrl},</if>
+ <if test="imageUrls != null">#{imageUrls},</if>
+ <if test="imageDeg != null">#{imageDeg},</if>
+ <if test="upImageTime != null">#{upImageTime},</if>
+ <if test="upImageOAid != null">#{upImageOAid},</if>
+ <if test="imageDel != null">#{imageDel},</if>
+ <if test="isAP != null">#{isAP},</if>
+ <if test="isAP_ID != null">#{isAP_ID},</if>
+ <if test="isAP_Time != null">#{isAP_Time},</if>
+ </trim>
+ </insert>
+
+ <update id="updateImageData" parameterType="ImageData">
+ update ImageData
+ <trim prefix="SET" suffixOverrides=",">
+ <if test="dOrdIDDt != null">DOrdIDDt = #{dOrdIDDt},</if>
+ <if test="sOrdIDDt != null">SOrdIDDt = #{sOrdIDDt},</if>
+ <if test="imageType != null">ImageType = #{imageType},</if>
+ <if test="imageUrl != null">ImageUrl = #{imageUrl},</if>
+ <if test="imageUrls != null">ImageUrls = #{imageUrls},</if>
+ <if test="imageDeg != null">ImageDeg = #{imageDeg},</if>
+ <if test="upImageTime != null">UpImageTime = #{upImageTime},</if>
+ <if test="upImageOAid != null">UpImageOAid = #{upImageOAid},</if>
+ <if test="imageDel != null">ImageDel = #{imageDel},</if>
+ <if test="isAP != null">isAP = #{isAP},</if>
+ <if test="isAP_ID != null">isAP_ID = #{isAP_ID},</if>
+ <if test="isAP_Time != null">isAP_Time = #{isAP_Time},</if>
+ </trim>
+ where id = #{id}
+ </update>
+
+ <delete id="deleteImageDataById" parameterType="Long">
+ delete from ImageData where id = #{id}
+ </delete>
+
+ <delete id="deleteImageDataByIds" parameterType="String">
+ delete from ImageData where id in
+ <foreach item="id" collection="array" open="(" separator="," close=")">
+ #{id}
+ </foreach>
+ </delete>
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysTaskAttachmentMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysTaskAttachmentMapper.xml
index dcda30a..49220e7 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysTaskAttachmentMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysTaskAttachmentMapper.xml
@@ -11,12 +11,13 @@
<result property="filePath" column="file_path" />
<result property="fileSize" column="file_size" />
<result property="fileType" column="file_type" />
+ <result property="attachmentCategory" column="attachment_category" />
<result property="uploadTime" column="upload_time" />
<result property="uploadBy" column="upload_by" />
</resultMap>
<sql id="selectSysTaskAttachmentVo">
- select attachment_id, task_id, file_name, file_path, file_size, file_type, upload_time, upload_by
+ select attachment_id, task_id, file_name, file_path, file_size, file_type, attachment_category, upload_time, upload_by
from sys_task_attachment
</sql>
@@ -26,6 +27,7 @@
<if test="taskId != null "> and task_id = #{taskId}</if>
<if test="fileName != null and fileName != ''"> and file_name like concat('%', #{fileName}, '%')</if>
<if test="fileType != null and fileType != ''"> and file_type = #{fileType}</if>
+ <if test="attachmentCategory != null and attachmentCategory != ''"> and attachment_category = #{attachmentCategory}</if>
<if test="uploadBy != null and uploadBy != ''"> and upload_by like concat('%', #{uploadBy}, '%')</if>
</where>
order by upload_time desc
@@ -50,6 +52,7 @@
<if test="filePath != null and filePath != ''">file_path,</if>
<if test="fileSize != null">file_size,</if>
<if test="fileType != null">file_type,</if>
+ <if test="attachmentCategory != null and attachmentCategory != ''">attachment_category,</if>
<if test="uploadTime != null">upload_time,</if>
<if test="uploadBy != null and uploadBy != ''">upload_by,</if>
</trim>
@@ -59,6 +62,7 @@
<if test="filePath != null and filePath != ''">#{filePath},</if>
<if test="fileSize != null">#{fileSize},</if>
<if test="fileType != null">#{fileType},</if>
+ <if test="attachmentCategory != null and attachmentCategory != ''">#{attachmentCategory},</if>
<if test="uploadTime != null">#{uploadTime},</if>
<if test="uploadBy != null and uploadBy != ''">#{uploadBy},</if>
</trim>
@@ -72,6 +76,7 @@
<if test="filePath != null and filePath != ''">file_path = #{filePath},</if>
<if test="fileSize != null">file_size = #{fileSize},</if>
<if test="fileType != null">file_type = #{fileType},</if>
+ <if test="attachmentCategory != null and attachmentCategory != ''">attachment_category = #{attachmentCategory},</if>
<if test="uploadTime != null">upload_time = #{uploadTime},</if>
<if test="uploadBy != null and uploadBy != ''">upload_by = #{uploadBy},</if>
</trim>
diff --git a/sql/update_attachment_category.sql b/sql/update_attachment_category.sql
new file mode 100644
index 0000000..6e363dc
--- /dev/null
+++ b/sql/update_attachment_category.sql
@@ -0,0 +1,8 @@
+-- 涓洪檮浠惰〃娣诲姞闄勪欢鍒嗙被瀛楁
+-- ----------------------------
+ALTER TABLE sys_task_attachment
+ADD COLUMN attachment_category VARCHAR(20) COMMENT '闄勪欢鍒嗙被锛�1-鐭ユ儏鍚屾剰涔︼紝2-鐥呬汉璧勬枡锛�3-鎿嶄綔璁板綍锛�4-鍑鸿溅鍓嶏紝5-鍑鸿溅鍚庯紝6-绯诲畨鍏ㄥ甫'
+AFTER file_type;
+
+-- 娣诲姞绱㈠紩
+ALTER TABLE sys_task_attachment ADD INDEX idx_attachment_category (attachment_category);
--
Gitblit v1.9.1