feat: 部分功能,新增附件上传功能,优化登录页面,修复bug。
This commit is contained in:
@@ -74,6 +74,23 @@
|
||||
<u--textarea v-model="form.remark" height="80rpx" placeholder="请填写备注" inputAlign="left"
|
||||
style="border: 2rpx solid #dcdfe6 !important; height: 160rpx;"></u--textarea>
|
||||
</u-form-item>
|
||||
<u-form-item label="附件图片" prop="attachment" labelPosition="top">
|
||||
<view class="upload-wrap">
|
||||
<view class="img-list">
|
||||
<view class="img-item" v-for="(img, index) in attachmentList" :key="index">
|
||||
<image :src="img" class="img-preview" mode="aspectFill" @click="previewImage(index)"></image>
|
||||
<view class="img-del" @click="deleteImage(index)">
|
||||
<uni-icons type="clear" size="20" color="#f5576c"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
<view class="img-add" v-if="attachmentList.length < 9" @click="chooseImage">
|
||||
<uni-icons type="plusempty" size="28" color="#667eea"></uni-icons>
|
||||
<text class="img-add-text">上传图片</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="upload-tip">最多上传9张图片,支持 jpg/png/jpeg 等格式</view>
|
||||
</view>
|
||||
</u-form-item>
|
||||
</u--form>
|
||||
<view class="form-btn">
|
||||
<u-button type="primary" text="提交" @click="submit"></u-button>
|
||||
@@ -105,8 +122,9 @@
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { getActivity, addActivity, updateActivity } from '@/api/health/activity'
|
||||
<script setup>
|
||||
import { getActivity, addActivity, updateActivity, uploadFile } from '@/api/health/activity'
|
||||
import config from '@/config'
|
||||
const { proxy } = getCurrentInstance()
|
||||
import { getDicts } from '@/api/system/dict/data.js'
|
||||
import dayjs from 'dayjs'
|
||||
@@ -144,6 +162,15 @@ const getInputStyle = (field) => {
|
||||
return errorFields.value.includes(field) ? inputErrorStyle : inputBaseStyle
|
||||
}
|
||||
|
||||
function normalizeAttachmentUrl(url) {
|
||||
if (!url) return ''
|
||||
if (url.startsWith('http')) return url
|
||||
// 附件是后端静态资源直链(如 /fileUrl/...、/profile/upload/...)
|
||||
// 需要用域名拼接,不能带网关前缀 prod-api(否则会 404)
|
||||
const origin = config.baseUrl.replace(/^(https?:\/\/[^/]+).*$/, '$1')
|
||||
return origin + url
|
||||
}
|
||||
|
||||
const birthdayShow = ref(false)
|
||||
const title = ref("活动记录")
|
||||
const startTimeShow = ref(false)
|
||||
@@ -154,6 +181,8 @@ const showType = ref(false)
|
||||
const flag = ref('add')
|
||||
const activityVolumeList = ref([])
|
||||
const showActivityVolume = ref(false)
|
||||
const attachmentList = ref([])
|
||||
const uploading = ref(false)
|
||||
|
||||
const data = reactive({
|
||||
form: {
|
||||
@@ -175,7 +204,8 @@ form: {
|
||||
remark: null,
|
||||
totalCost: 0,
|
||||
partner: null,
|
||||
costDetail: null
|
||||
costDetail: null,
|
||||
attachment: null
|
||||
},
|
||||
rules: {
|
||||
name: [{ required: true, message: '活动名称不能为空', trigger:['change', 'blur'] }],
|
||||
@@ -245,6 +275,9 @@ function getData() {
|
||||
if(form.value.id!=null){
|
||||
getActivity(form.value.id).then(res => {
|
||||
form.value = res.data
|
||||
if (form.value.attachment) {
|
||||
attachmentList.value = form.value.attachment.split(',').filter(url => url).map(normalizeAttachmentUrl)
|
||||
}
|
||||
// 类型
|
||||
getDicts('activity_type').then(result => {
|
||||
form.value.typeName=dictStr(form.value.type, result.data)
|
||||
@@ -298,6 +331,7 @@ function getData() {
|
||||
function submit() {
|
||||
// 清空错误字段
|
||||
errorFields.value = []
|
||||
form.value.attachment = attachmentList.value.join(',')
|
||||
|
||||
proxy.$refs['uForm'].validate().then(() => {
|
||||
if (form.value.id != null) {
|
||||
@@ -336,6 +370,65 @@ function submit() {
|
||||
proxy.$modal.msgError('请填写完整信息')
|
||||
})
|
||||
}
|
||||
|
||||
function chooseImage() {
|
||||
if (uploading.value) {
|
||||
proxy.$refs['uToast'].show({ message: '正在上传中,请稍候', type: 'warning' })
|
||||
return
|
||||
}
|
||||
uni.chooseImage({
|
||||
count: 9 - attachmentList.value.length,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: (res) => {
|
||||
uploadImages(res.tempFilePaths, 0)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function uploadImages(paths, index) {
|
||||
if (index >= paths.length) {
|
||||
uploading.value = false
|
||||
return
|
||||
}
|
||||
uploading.value = true
|
||||
uni.showLoading({ title: `上传中 ${index + 1}/${paths.length}`, mask: true })
|
||||
uploadFile({
|
||||
filePath: paths[index],
|
||||
name: 'file'
|
||||
}).then(res => {
|
||||
const url = (res.data && res.data.url) || res.fileName || res.url
|
||||
if (url) {
|
||||
attachmentList.value.push(normalizeAttachmentUrl(url))
|
||||
}
|
||||
uni.hideLoading()
|
||||
uploadImages(paths, index + 1)
|
||||
}).catch(() => {
|
||||
uni.hideLoading()
|
||||
uploading.value = false
|
||||
proxy.$refs['uToast'].show({ message: `第 ${index + 1} 张上传失败`, type: 'error' })
|
||||
})
|
||||
}
|
||||
|
||||
function deleteImage(index) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定删除这张图片吗?',
|
||||
confirmColor: '#f5576c',
|
||||
success: (modalRes) => {
|
||||
if (modalRes.confirm) {
|
||||
attachmentList.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function previewImage(index) {
|
||||
uni.previewImage({
|
||||
urls: attachmentList.value,
|
||||
current: attachmentList.value[index]
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -390,6 +483,69 @@ function submit() {
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-wrap {
|
||||
width: 100%;
|
||||
|
||||
.img-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.img-item {
|
||||
position: relative;
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.img-preview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.img-del {
|
||||
position: absolute;
|
||||
top: 6rpx;
|
||||
right: 6rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.img-add {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
border: 2rpx dashed rgba(102, 126, 234, 0.55);
|
||||
border-radius: 12rpx;
|
||||
background: rgba(102, 126, 234, 0.06);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.img-add-text {
|
||||
color: #667eea;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.upload-tip {
|
||||
font-size: 22rpx;
|
||||
color: #909399;
|
||||
line-height: 1.4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -84,6 +84,19 @@
|
||||
<text class="info-label">备注</text>
|
||||
<text class="info-value">{{ item.remark }}</text>
|
||||
</view>
|
||||
<view class="info-item info-item-full" v-if="parseAttachment(item.attachment).length">
|
||||
<text class="info-label">附件</text>
|
||||
<view class="attachment-list">
|
||||
<image
|
||||
v-for="(img, imgIdx) in parseAttachment(item.attachment)"
|
||||
:key="imgIdx"
|
||||
:src="img"
|
||||
class="attachment-thumb"
|
||||
mode="aspectFill"
|
||||
@click.stop="previewAttachment(parseAttachment(item.attachment), imgIdx)"
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -180,6 +193,7 @@ import { getDicts } from '@/api/system/dict/data.js'
|
||||
import { timeHandler } from '@/utils/common.ts'
|
||||
import {onLoad,onShow} from "@dcloudio/uni-app";
|
||||
import dayjs from 'dayjs'
|
||||
import config from '@/config'
|
||||
// 计算属性与监听属性是在vue中而非uniap中 需要注意!!!
|
||||
import {reactive ,toRefs,ref,computed }from "vue";
|
||||
const pageNum = ref(1)
|
||||
@@ -409,6 +423,23 @@ function getList() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function parseAttachment(attachment) {
|
||||
if (!attachment) return []
|
||||
// 附件是后端静态资源直链,需要用域名拼接,不能带网关前缀 prod-api
|
||||
const origin = config.baseUrl.replace(/^(https?:\/\/[^/]+).*$/, '$1')
|
||||
return attachment.split(',').filter(url => url).map(url => {
|
||||
if (url.startsWith('http')) return url
|
||||
return origin + url
|
||||
})
|
||||
}
|
||||
|
||||
function previewAttachment(urls, index) {
|
||||
uni.previewImage({
|
||||
urls: urls,
|
||||
current: urls[index]
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
@@ -489,6 +520,27 @@ function getList() {
|
||||
border: 1rpx solid rgba(19, 194, 194, 0.3);
|
||||
}
|
||||
|
||||
.attachment-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12rpx;
|
||||
margin-top: 4rpx;
|
||||
width: 100%;
|
||||
|
||||
.attachment-thumb {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 8rpx;
|
||||
background: #f5f7fa;
|
||||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.08);
|
||||
transition: transform 0.2s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 费用汇总面板 ====================
|
||||
.summary-mask {
|
||||
position: fixed;
|
||||
|
||||
Reference in New Issue
Block a user