797 lines
24 KiB
Vue
Raw Normal View History

2025-10-15 20:21:34 +08:00
<!-- 任务执行提交页面 -->
2025-10-07 08:58:02 +08:00
<template>
2025-10-15 20:21:34 +08:00
<view class="rw-detail-page" :class="{ 'readonly-mode': isReadOnly }">
2025-10-11 21:11:16 +08:00
<!-- 提交遮罩层 -->
<view v-if="isSubmitting" class="submit-overlay">
<view class="submit-loading">
<view class="loading-spinner"></view>
<text class="loading-text">提交中...</text>
</view>
</view>
2025-10-07 08:58:02 +08:00
<view v-if="isLoading" class="loading-indicator">加载中...</view>
2025-10-15 20:21:34 +08:00
<view v-else class="content-wrapper">
<view class="p-15">
<!-- 第一部分任务要求 -->
<view class="rw-info-section">
<view class="section-title">任务要求</view>
<!-- 只读模式提示 -->
<view v-if="isReadOnly" class="readonly-tip">
<text class="tip-text">📖 只读模式 - 查看已提交的内容</text>
</view>
<!-- 任务名称 -->
<view class="info-item">
<text class="label">任务名称</text>
<text class="value title-bold">{{ rw.rwmc }}</text>
</view>
<!-- 任务描述 -->
<view v-if="rw.rwms" class="info-item">
<text class="label">任务描述</text>
<text class="value">{{ rw.rwms }}</text>
</view>
<!-- 任务时间 -->
<view v-if="rw.rwkstime" class="info-item">
<text class="label">任务时间</text>
<text class="value">{{ rw.rwkstime }}</text>
</view>
<!-- 附件预览 -->
<BasicFilePreview
v-if="rw.rwfj && rw.fjmx"
:file-url="rw.rwfj"
:file-name="rw.fjmx"
:file-format="getFileFormat(rw.fjmx)"
class="mt-15"
/>
2025-10-11 21:11:16 +08:00
</view>
2025-10-15 20:21:34 +08:00
<!-- 第二部分任务执行 -->
<view class="rw-execute-section">
<view class="section-title">任务执行</view>
<view class="execute-form">
<BasicForm :schema="schema" v-model="formData" :disabled="isReadOnly">
</BasicForm>
</view>
2025-10-07 08:58:02 +08:00
</view>
</view>
</view>
2025-10-15 20:21:34 +08:00
<!-- 提交按钮 - 固定在底部 -->
<view v-if="!isReadOnly" class="submit-button-fixed">
<button class="action-button" @click="saveRwZx" :disabled="isSubmitting">
{{ isSubmitting ? '提交中...' : '提交' }}
</button>
</view>
2025-10-07 08:58:02 +08:00
</view>
</template>
<script lang="ts" setup>
2025-10-11 21:11:16 +08:00
import {ref, reactive} from 'vue';
2025-10-07 08:58:02 +08:00
import {onLoad} from '@dcloudio/uni-app';
import {rwFindInfoByRwId, rwflFindRwlxsByRwId, rwzxExecutedInfoByRwIdAndJsApi, rwzxSaveApi} from "@/api/base/server";
import {useForm} from "@/components/BasicForm/hooks/useForm";
import {navigateBack, showToast} from "@/utils/uniapp";
import {useUserStore} from "@/store/modules/user";
import { ImageVideoUpload, type FileItem, COMPRESS_PRESETS } from "@/components/ImageVideoUpload";
import { attachmentUpload } from "@/api/system/upload";
2025-10-15 20:21:34 +08:00
import BasicFilePreview from "@/components/BasicFile/preview.vue";
2025-10-07 08:58:02 +08:00
interface MessageDetail {
id: string; // Assuming an ID is passed or can be derived
title: string;
desc: string;
date: string;
timeAgo: string;
tagText: string;
tagType: string;
2025-10-15 20:21:34 +08:00
likes?: number;
comments?: number;
2025-10-07 08:58:02 +08:00
// Add other fields as necessary
}
2025-10-15 20:21:34 +08:00
interface RwInfo {
id?: string;
rwmc?: string; // 任务名称
rwms?: string; // 任务描述
rwkstime?: string; // 任务开始时间
rwfj?: string; // 任务附件URL
fjmx?: string; // 附件名称
rwlxes?: any[]; // 任务类型列表
rwzxqds?: any[]; // 任务执行清单
[key: string]: any; // 允许其他属性
}
2025-10-07 08:58:02 +08:00
const formData: any = ref({})
const messageId = ref<string>('');
const jsId = ref<string>(''); // 教师ID
const executionId = ref<string>(''); // 执行ID
2025-10-11 21:11:16 +08:00
const isReadOnly = ref<boolean>(false); // 只读模式
const isSubmitting = ref<boolean>(false); // 提交状态
const submitTimer = ref<any>(null); // 防抖定时器
2025-10-07 08:58:02 +08:00
const messageDetail = ref<MessageDetail | null>({
id: 'todo1',
title: '教务通知 (待办)',
desc: '学校召开期初教学准备会议暨首次教学工作例会. 会议强调了新学期的教学重点和要求,请各位老师认真准备。',
date: '2025-02-17',
timeAgo: '8 mins 前',
tagText: '通知',
tagType: 'notice',
likes: 6,
comments: 12
});
const isLoading = ref(false);
const rwflx: any = ref([])
2025-10-15 20:21:34 +08:00
const rw = ref<RwInfo>({})
2025-10-11 21:11:16 +08:00
const schema = ref<FormsSchema[]>([])
2025-10-07 08:58:02 +08:00
const {getUser} = useUserStore()
async function saveRwZx() {
2025-10-11 21:11:16 +08:00
// 防抖处理
if (isSubmitting.value) {
console.log('正在提交中,请勿重复点击');
return;
}
// 清除之前的定时器
if (submitTimer.value) {
clearTimeout(submitTimer.value);
}
// 设置防抖延迟
submitTimer.value = setTimeout(async () => {
await performSubmit();
}, 300);
}
async function performSubmit() {
if (isSubmitting.value) {
return;
}
isSubmitting.value = true;
try {
const result = [];
for (let i = 0; i < rwflx.value.length; i++) {
2025-10-07 08:58:02 +08:00
const fieldId = rwflx.value[i].id;
let fieldValue = formData.value[fieldId];
// 处理上传类型的任务
2025-10-11 21:11:16 +08:00
let fileNames = '';
2025-10-07 08:58:02 +08:00
if (rwflx.value[i].rwfl == "sctp" || rwflx.value[i].rwfl == "scsp" || rwflx.value[i].rwfl == "scwd") {
2025-10-11 21:11:16 +08:00
// 收集上传文件的URL和文件名
2025-10-07 08:58:02 +08:00
const fileUrls = [];
2025-10-11 21:11:16 +08:00
const names = [];
2025-10-07 08:58:02 +08:00
if (rwflx.value[i].rwfl == "sctp") {
// 图片上传
2025-10-11 21:11:16 +08:00
const images = formData.value[`${fieldId}_imageList`] || [];
images.forEach((img: any) => {
if (img.url) {
fileUrls.push(img.url);
names.push(img.name || img.url.split('/').pop() || 'image.jpg');
}
});
2025-10-07 08:58:02 +08:00
} else if (rwflx.value[i].rwfl == "scsp") {
// 视频上传
2025-10-11 21:11:16 +08:00
const videos = formData.value[`${fieldId}_videoList`] || [];
videos.forEach((video: any) => {
if (video.url) {
fileUrls.push(video.url);
names.push(video.name || video.url.split('/').pop() || 'video.mp4');
}
});
2025-10-07 08:58:02 +08:00
} else if (rwflx.value[i].rwfl == "scwd") {
// 文档上传
2025-10-11 21:11:16 +08:00
const files = formData.value[`${fieldId}_fileList`] || [];
files.forEach((file: any) => {
if (file.url) {
fileUrls.push(file.url);
names.push(file.name || file.url.split('/').pop() || 'document');
}
});
2025-10-07 08:58:02 +08:00
}
fieldValue = fileUrls.join(',');
2025-10-11 21:11:16 +08:00
fileNames = names.join(',');
2025-10-07 08:58:02 +08:00
}
2025-10-11 21:11:16 +08:00
// 验证必填项 - 针对上传类型使用不同的判断方式
if (rwflx.value[i].rwbs) {
let isEmpty = false;
if (rwflx.value[i].rwfl == "sctp" || rwflx.value[i].rwfl == "scsp" || rwflx.value[i].rwfl == "scwd") {
// 上传类型的验证:检查是否有上传的文件
if (rwflx.value[i].rwfl == "sctp") {
const images = formData.value[`${fieldId}_imageList`] || [];
isEmpty = images.length === 0;
} else if (rwflx.value[i].rwfl == "scsp") {
const videos = formData.value[`${fieldId}_videoList`] || [];
isEmpty = videos.length === 0;
} else if (rwflx.value[i].rwfl == "scwd") {
const files = formData.value[`${fieldId}_fileList`] || [];
isEmpty = files.length === 0;
}
} else {
// 非上传类型的验证:检查字段值是否为空
isEmpty = !fieldValue || fieldValue == "";
}
if (isEmpty) {
showToast("请填写必填项!")
isSubmitting.value = false;
return;
}
2025-10-07 08:58:02 +08:00
}
2025-10-11 21:11:16 +08:00
// 查找对应的执行记录ID
const existingRecord = rwzxqds.value.find(item => item.rwlxId === fieldId);
const recordId = existingRecord ? existingRecord.id : undefined;
2025-10-07 08:58:02 +08:00
result.push({
2025-10-11 21:11:16 +08:00
id: recordId, // 如果有现有记录则保留ID否则为undefined新增
2025-10-07 08:58:02 +08:00
rwlxId: fieldId,
rwzxqdtx: fieldValue,
2025-10-11 21:11:16 +08:00
wjmc: fileNames || undefined, // 文件名,只有上传类型才有
2025-10-07 08:58:02 +08:00
})
}
await rwzxSaveApi({
id: executionId.value, // 执行记录ID如果有的话就是更新没有就是新增
rwId: rw.value.id, // 任务ID
rwzxfzr: jsId.value || getUser.id, // 执行人教师ID
mobile: getUser.mobile, // 手机号
rwzxqdDtos: result // 执行清单
})
showToast("操作成功!");
2025-10-11 21:11:16 +08:00
2025-10-15 20:21:34 +08:00
// 发送刷新事件
uni.$emit('refreshTaskExecution');
2025-10-11 21:11:16 +08:00
// 延迟一下再跳转,让用户看到成功提示
setTimeout(() => {
2025-10-15 20:21:34 +08:00
// 返回到任务执行页面
uni.navigateBack();
2025-10-11 21:11:16 +08:00
}, 1500);
} catch (error) {
console.error('提交失败:', error);
showToast("提交失败,请重试");
} finally {
isSubmitting.value = false;
}
2025-10-07 08:58:02 +08:00
}
2025-10-15 20:21:34 +08:00
// 获取文件格式
const getFileFormat = (fileName: string) => {
if (!fileName) return '';
const parts = fileName.split('.');
return parts.length > 1 ? parts[parts.length - 1].toLowerCase() : '';
};
2025-10-11 21:11:16 +08:00
const rwzxqds = ref<any[]>([])
onLoad(async (options: any) => {
2025-10-07 08:58:02 +08:00
console.log('页面加载参数:', options);
let taskId = '';
2025-10-11 21:11:16 +08:00
// 从全局存储中获取参数数据
const storedParams = uni.getStorageSync('taskSubmitData');
if (storedParams) {
2025-10-07 08:58:02 +08:00
try {
2025-10-11 21:11:16 +08:00
taskId = storedParams.id;
jsId.value = storedParams.jsId || '';
executionId.value = storedParams.executionId || '';
isReadOnly.value = storedParams.isReadOnly || false;
console.log('从全局存储解析参数成功:', { taskId, jsId: jsId.value, executionId: executionId.value, isReadOnly: isReadOnly.value });
// 清除存储的参数数据
uni.removeStorageSync('taskSubmitData');
2025-10-07 08:58:02 +08:00
} catch (error) {
2025-10-11 21:11:16 +08:00
console.error('解析全局存储参数失败:', error);
2025-10-07 08:58:02 +08:00
taskId = options.id || '';
}
2025-10-11 21:11:16 +08:00
} else {
// 兼容原有的URL参数方式向后兼容
if (options && options.params) {
try {
const params = JSON.parse(decodeURIComponent(options.params));
taskId = params.id;
jsId.value = params.jsId || '';
executionId.value = params.executionId || '';
isReadOnly.value = params.isReadOnly || false;
console.log('解析URL参数成功:', { taskId, jsId: jsId.value, executionId: executionId.value, isReadOnly: isReadOnly.value });
} catch (error) {
console.error('解析URL参数失败:', error);
taskId = options.id || '';
}
} else if (options && options.id) {
taskId = options.id;
}
2025-10-07 08:58:02 +08:00
}
if (taskId) {
const {result} = await rwFindInfoByRwId({
rwId: taskId
});
rwflx.value = result.rwlxes;
rw.value = result;
for (let i = 0; i < rwflx.value.length; i++) {
// 处理上传类型的任务
if (rwflx.value[i].rwfl == "sctp" || rwflx.value[i].rwfl == "scsp" || rwflx.value[i].rwfl == "scwd") {
// 初始化表单数据
const fieldId = rwflx.value[i].id;
if (rwflx.value[i].rwfl == "sctp") {
2025-10-11 21:11:16 +08:00
formData.value[`${fieldId}_imageList`] = [];
2025-10-07 08:58:02 +08:00
} else if (rwflx.value[i].rwfl == "scsp") {
2025-10-11 21:11:16 +08:00
formData.value[`${fieldId}_videoList`] = [];
2025-10-07 08:58:02 +08:00
} else if (rwflx.value[i].rwfl == "scwd") {
2025-10-11 21:11:16 +08:00
formData.value[`${fieldId}_fileList`] = [];
2025-10-07 08:58:02 +08:00
}
// 根据任务类型配置上传组件
let componentConfig = {};
if (rwflx.value[i].rwfl == "sctp") {
// 上传图片
componentConfig = {
component: "ImageVideoUpload",
componentProps: {
enableImage: true,
enableVideo: false,
enableFile: false,
2025-10-11 21:11:16 +08:00
maxImageCount: 30,
2025-10-07 08:58:02 +08:00
uploadApi: attachmentUpload,
2025-10-11 21:11:16 +08:00
compressConfig: COMPRESS_PRESETS.medium,
imageList: formData.value[`${fieldId}_imageList`] || []
2025-10-07 08:58:02 +08:00
}
};
} else if (rwflx.value[i].rwfl == "scsp") {
// 上传视频
componentConfig = {
component: "ImageVideoUpload",
componentProps: {
enableImage: false,
enableVideo: true,
enableFile: false,
2025-10-11 21:11:16 +08:00
maxVideoCount: 30,
2025-10-07 08:58:02 +08:00
uploadApi: attachmentUpload,
2025-10-11 21:11:16 +08:00
compressConfig: COMPRESS_PRESETS.medium,
videoList: formData.value[`${fieldId}_videoList`] || []
2025-10-07 08:58:02 +08:00
}
};
} else if (rwflx.value[i].rwfl == "scwd") {
// 上传文档
componentConfig = {
component: "ImageVideoUpload",
componentProps: {
enableImage: false,
enableVideo: false,
enableFile: true,
2025-10-11 21:11:16 +08:00
maxFileCount: 30,
2025-10-07 08:58:02 +08:00
allowedFileTypes: ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'mp3', 'wav', 'zip', 'rar'],
uploadApi: attachmentUpload,
2025-10-11 21:11:16 +08:00
compressConfig: COMPRESS_PRESETS.medium,
fileList: formData.value[`${fieldId}_fileList`] || []
2025-10-07 08:58:02 +08:00
}
};
}
2025-10-11 21:11:16 +08:00
// 对于上传类型,使用特殊的字段名
const schemaField = rwflx.value[i].rwfl === "sctp" ? `${rwflx.value[i].id}_imageList` :
rwflx.value[i].rwfl === "scsp" ? `${rwflx.value[i].id}_videoList` :
rwflx.value[i].rwfl === "scwd" ? `${rwflx.value[i].id}_fileList` :
`${rwflx.value[i].id}`;
schema.value.push({
field: schemaField,
2025-10-07 08:58:02 +08:00
label: `${rwflx.value[i].rwbt}`,
2025-10-11 21:11:16 +08:00
required: rwflx.value[i].rwbs && !isReadOnly.value, // 只读模式下不要求必填
2025-10-07 08:58:02 +08:00
itemProps: {
labelPosition: "top",
},
2025-10-11 21:11:16 +08:00
...componentConfig,
componentProps: {
...componentConfig.componentProps,
disabled: isReadOnly.value // 禁用上传组件
}
2025-10-07 08:58:02 +08:00
})
} else if (rwflx.value[i].rwfl == "text") {
2025-10-11 21:11:16 +08:00
schema.value.push({
2025-10-07 08:58:02 +08:00
field: `${rwflx.value[i].id}`,
label: `${rwflx.value[i].rwbt}`,
component: "BasicInput",
2025-10-11 21:11:16 +08:00
required: rwflx.value[i].rwbs && !isReadOnly.value, // 只读模式下不要求必填
2025-10-07 08:58:02 +08:00
itemProps: {
labelPosition: "top",
},
componentProps: {
type: "textarea",
2025-10-11 21:11:16 +08:00
placeholder: isReadOnly.value ? "" : "请输入内容",
disabled: isReadOnly.value // 禁用文本输入
2025-10-07 08:58:02 +08:00
},
})
} else if (rwflx.value[i].rwfl == "dxsx" || rwflx.value[i].rwfl == "dxxz") {
let options = rwflx.value[i].remark.split("");
let range = [];
2025-10-11 21:11:16 +08:00
for (let j = 0; j < options.length; j++) {
2025-10-07 08:58:02 +08:00
range.push({
2025-10-11 21:11:16 +08:00
name: options[j]
2025-10-07 08:58:02 +08:00
});
}
2025-10-11 21:11:16 +08:00
schema.value.push({
2025-10-07 08:58:02 +08:00
field: `${rwflx.value[i].id}`,
label: `${rwflx.value[i].rwbt}`,
component: "BasicPicker",
2025-10-11 21:11:16 +08:00
required: rwflx.value[i].rwbs && !isReadOnly.value, // 只读模式下不要求必填
2025-10-07 08:58:02 +08:00
itemProps: {
labelPosition: "top",
},
componentProps: {
range: range,
rangeKey: "name",
savaKey: "name",
2025-10-11 21:11:16 +08:00
disabled: isReadOnly.value // 禁用选择器
2025-10-07 08:58:02 +08:00
},
})
}
}
2025-10-11 21:11:16 +08:00
2025-10-07 08:58:02 +08:00
const res = await rwzxExecutedInfoByRwIdAndJsApi({
rwId: taskId,
jsId: jsId.value || getUser.id // 使用传入的jsId如果没有则使用当前用户ID
});
if (res && res.result && res.result.length) {
rwzxqds.value = res.result;
const showData = {};
2025-10-11 21:11:16 +08:00
2025-10-07 08:58:02 +08:00
for (let i = 0; i < rwzxqds.value.length; i++) {
2025-10-11 21:11:16 +08:00
const record = rwzxqds.value[i];
const rwlxId = record.rwlxId;
const rwzxqdtx = record.rwzxqdtx;
// 查找对应的任务类型
const taskType = rwflx.value.find(item => item.id === rwlxId);
if (taskType) {
if (taskType.rwfl === "sctp") {
// 图片上传类型 - 解析URL和文件名并创建图片对象
if (rwzxqdtx) {
const urls = rwzxqdtx.split(',').filter(Boolean);
const names = record.wjmc ? record.wjmc.split(',').filter(Boolean) : [];
const images = urls.map((url, index) => ({
url: url.trim(),
name: names[index] || url.split('/').pop() || 'image.jpg',
tempPath: undefined
}));
showData[`${rwlxId}_imageList`] = images;
}
} else if (taskType.rwfl === "scsp") {
// 视频上传类型
if (rwzxqdtx) {
const urls = rwzxqdtx.split(',').filter(Boolean);
const names = record.wjmc ? record.wjmc.split(',').filter(Boolean) : [];
const videos = urls.map((url, index) => ({
url: url.trim(),
name: names[index] || url.split('/').pop() || 'video.mp4',
tempPath: undefined
}));
showData[`${rwlxId}_videoList`] = videos;
}
} else if (taskType.rwfl === "scwd") {
// 文档上传类型
if (rwzxqdtx) {
const urls = rwzxqdtx.split(',').filter(Boolean);
const names = record.wjmc ? record.wjmc.split(',').filter(Boolean) : [];
const files = urls.map((url, index) => ({
url: url.trim(),
name: names[index] || url.split('/').pop() || 'document',
tempPath: undefined,
type: 'document',
extension: url.split('.').pop() || ''
}));
showData[`${rwlxId}_fileList`] = files;
}
} else {
// 文本等其他类型
showData[rwlxId] = rwzxqdtx;
}
}
}
// 合并已保存的数据,而不是完全覆盖
formData.value = { ...formData.value, ...showData };
// 更新 schema 中上传组件的初始值
for (let i = 0; i < schema.value.length; i++) {
const schemaItem = schema.value[i];
if (schemaItem.component === "ImageVideoUpload" && schemaItem.field) {
const fieldName = schemaItem.field;
if (fieldName.includes('_imageList') && formData.value[fieldName]) {
schemaItem.componentProps.imageList = formData.value[fieldName];
} else if (fieldName.includes('_videoList') && formData.value[fieldName]) {
schemaItem.componentProps.videoList = formData.value[fieldName];
} else if (fieldName.includes('_fileList') && formData.value[fieldName]) {
schemaItem.componentProps.fileList = formData.value[fieldName];
}
}
2025-10-07 08:58:02 +08:00
}
2025-10-11 21:11:16 +08:00
// 调试:输出回显数据
console.log('数据回显 - showData:', showData);
console.log('数据回显 - formData.value:', formData.value);
console.log('更新后的 schema:', schema.value);
// 调试:输出文件名处理情况
console.log('文件名处理 - rwzxqds.value:', rwzxqds.value);
2025-10-07 08:58:02 +08:00
}
} else {
console.error('Message ID/Data is missing!');
uni.showToast({title: '加载失败,缺少信息', icon: 'none'});
}
});
</script>
<style scoped lang="scss">
2025-10-15 20:21:34 +08:00
.rw-detail-page {
2025-10-07 08:58:02 +08:00
background-color: #f4f5f7;
min-height: 100vh;
2025-10-15 20:21:34 +08:00
padding-bottom: 80px; // 为底部按钮留出空间
2025-10-07 08:58:02 +08:00
box-sizing: border-box;
}
2025-10-15 20:21:34 +08:00
.loading-indicator {
2025-10-07 08:58:02 +08:00
text-align: center;
color: #999;
padding: 40px 15px;
font-size: 14px;
}
2025-10-15 20:21:34 +08:00
.content-wrapper {
.p-15 {
padding: 15px;
}
.mt-15 {
margin-top: 15px;
}
2025-10-07 08:58:02 +08:00
}
2025-10-15 20:21:34 +08:00
// 第一部分:任务要求
.rw-info-section {
2025-10-07 08:58:02 +08:00
margin-bottom: 20px;
2025-10-15 20:21:34 +08:00
padding: 15px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
.section-title {
font-size: 16px;
2025-10-07 08:58:02 +08:00
font-weight: bold;
2025-10-15 20:21:34 +08:00
margin-bottom: 15px;
2025-10-07 08:58:02 +08:00
color: #333;
2025-10-15 20:21:34 +08:00
border-bottom: 2px solid #007aff;
padding-bottom: 5px;
2025-10-07 08:58:02 +08:00
}
2025-10-15 20:21:34 +08:00
2025-10-11 21:11:16 +08:00
.readonly-tip {
2025-10-15 20:21:34 +08:00
margin-bottom: 15px;
2025-10-11 21:11:16 +08:00
padding: 8px 12px;
background-color: #e6f7ff;
border: 1px solid #91d5ff;
border-radius: 4px;
.tip-text {
font-size: 12px;
color: #1890ff;
}
}
2025-10-15 20:21:34 +08:00
.info-item {
display: flex;
margin-bottom: 15px;
&:last-child {
margin-bottom: 0;
}
.label {
width: 80px;
color: #666;
font-size: 14px;
flex-shrink: 0;
}
.value {
flex: 1;
color: #333;
font-size: 14px;
word-break: break-word;
&.title-bold {
font-weight: bold;
font-size: 16px;
}
2025-10-07 08:58:02 +08:00
}
}
}
2025-10-15 20:21:34 +08:00
// 第二部分:任务执行
.rw-execute-section {
margin-bottom: 20px;
padding: 15px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
.section-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 15px;
color: #333;
border-bottom: 2px solid #007aff;
padding-bottom: 5px;
2025-10-07 08:58:02 +08:00
}
2025-10-11 21:11:16 +08:00
2025-10-15 20:21:34 +08:00
.execute-form {
padding-top: 5px;
2025-10-11 21:11:16 +08:00
}
2025-10-15 20:21:34 +08:00
}
// 提交按钮 - 固定在底部
.submit-button-fixed {
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 15px;
background-color: #fff;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
z-index: 10;
border-top: 1px solid #eee;
2025-10-11 21:11:16 +08:00
2025-10-15 20:21:34 +08:00
.action-button {
width: 100%;
height: 44px;
line-height: 44px;
font-size: 16px;
font-weight: 500;
border-radius: 8px;
background-color: #409eff;
color: #ffffff;
border: none;
&:active:not(:disabled) {
background-color: #3a8ee6;
transform: translateY(1px);
}
&:disabled {
background-color: #d9d9d9 !important;
color: #999 !important;
cursor: not-allowed;
opacity: 0.6;
}
2025-10-11 21:11:16 +08:00
}
2025-10-07 08:58:02 +08:00
}
2025-10-15 20:21:34 +08:00
// 为输入框添加基本边框
2025-10-07 08:58:02 +08:00
:deep(.uni-input),
:deep(.uni-textarea) {
width: 100% !important;
min-height: 35px !important;
font-size: 13px !important;
border: 1px #CCCCCC solid !important;
border-radius: 3px !important;
padding: 8px 12px !important;
box-sizing: border-box !important;
}
:deep(input),
:deep(textarea) {
width: 100% !important;
min-height: 35px !important;
font-size: 13px !important;
border: 1px #CCCCCC solid !important;
border-radius: 3px !important;
padding: 8px 12px !important;
box-sizing: border-box !important;
}
2025-10-15 20:21:34 +08:00
// 为 BasicForm 中的 label 添加样式
:deep(.basic-form) {
.form-label,
.label,
.uni-form-item__label {
width: 100% !important;
white-space: normal !important;
word-break: break-word !important;
font-size: 15px !important;
font-weight: bold !important;
color: #333 !important;
text-align: left !important;
display: block !important;
line-height: 1.4 !important;
max-width: 100% !important;
overflow-wrap: break-word !important;
}
}
// 直接针对包含标签文本的 view 元素
:deep(view) {
white-space: normal !important;
word-break: normal !important;
overflow-wrap: break-word !important;
}
2025-10-11 21:11:16 +08:00
// 只读模式样式
.readonly-mode {
:deep(input),
:deep(textarea),
:deep(.uni-input),
:deep(.uni-textarea) {
background-color: #f5f5f5 !important;
color: #666 !important;
cursor: not-allowed !important;
}
:deep(.upload-container),
:deep(.picker-container) {
opacity: 0.6;
pointer-events: none;
}
}
// 提交遮罩层样式
.submit-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
}
.submit-loading {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #fff;
padding: 30px;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid #f3f3f3;
2025-10-15 20:21:34 +08:00
border-top: 3px solid #409eff;
2025-10-11 21:11:16 +08:00
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 16px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-text {
font-size: 16px;
color: #333;
font-weight: 500;
}
2025-10-07 08:58:02 +08:00
</style>