开始开发功能实现
This commit is contained in:
parent
4bf4371fcb
commit
08cebe614b
|
|
@ -142,3 +142,18 @@ export const deleteProject = (ids) => {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 开始项目开发
|
||||
* @param {Object} data
|
||||
* @param {string} data.id 项目ID
|
||||
* @param {string} data.expectedCompleteDate 预计完成日期(YYYY-MM-DD)
|
||||
* @returns {Promise} 操作结果
|
||||
*/
|
||||
export const startProjectDevelopment = (data) => {
|
||||
return uni.$uv.http.put('bst/project/start', data, {
|
||||
custom: {
|
||||
auth: true
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -201,13 +201,54 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 开始开发弹窗 -->
|
||||
<view v-if="showStartModal" class="start-modal">
|
||||
<view class="modal-mask" @click="closeStartModal"></view>
|
||||
<view class="modal-panel">
|
||||
<view class="modal-header">
|
||||
<text class="modal-title">开始开发</text>
|
||||
<text class="modal-close" @click="closeStartModal">✕</text>
|
||||
</view>
|
||||
<view class="modal-body">
|
||||
<text class="modal-subtitle" v-if="currentStartProjectName">项目:{{ currentStartProjectName }}</text>
|
||||
<view class="field">
|
||||
<text class="field-label">预计完成日期</text>
|
||||
<view class="date-input" @click="openStartDatePicker">
|
||||
<text class="placeholder" v-if="!startProjectForm.expectedCompleteDate">请选择预计完成日期</text>
|
||||
<text class="value" v-else>{{ startProjectForm.expectedCompleteDate }}</text>
|
||||
<text class="date-icon">📅</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="modal-actions">
|
||||
<uv-button size="small" @click="closeStartModal" :disabled="startingProject">取消</uv-button>
|
||||
<uv-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="submitStartDevelopment"
|
||||
:loading="startingProject"
|
||||
:disabled="startingProject"
|
||||
>
|
||||
确定
|
||||
</uv-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<uv-datetime-picker
|
||||
ref="startDatePickerRef"
|
||||
v-model="startDatePickerValue"
|
||||
mode="date"
|
||||
@confirm="onStartDateConfirm"
|
||||
></uv-datetime-picker>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watch, onMounted, nextTick, onUnmounted } from 'vue';
|
||||
import { ref, reactive, computed, watch, onMounted, nextTick, onUnmounted } from 'vue';
|
||||
import { onLoad, onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app';
|
||||
import { getProjectList, getUserList, deleteProject } from '@/api';
|
||||
import { getProjectList, getUserList, deleteProject, startProjectDevelopment } from '@/api';
|
||||
import { usePagination } from '@/composables';
|
||||
import { useDictStore } from '@/store/dict';
|
||||
import { useUserStore } from '@/store/user';
|
||||
|
|
@ -414,9 +455,35 @@ const getStatusType = (status) => {
|
|||
// 格式化日期
|
||||
const formatDate = (dateStr) => {
|
||||
if (!dateStr) return '未知';
|
||||
if (typeof dateStr === 'number') {
|
||||
return formatDateValue(dateStr);
|
||||
}
|
||||
return dateStr.split(' ')[0];
|
||||
};
|
||||
|
||||
const formatDateValue = (value) => {
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) return '';
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
};
|
||||
|
||||
const extractDateOnly = (value) => {
|
||||
if (!value) return '';
|
||||
if (typeof value === 'string') {
|
||||
const trimmed = value.trim();
|
||||
if (/^\d{4}-\d{2}-\d{2}$/.test(trimmed)) {
|
||||
return trimmed;
|
||||
}
|
||||
if (trimmed.includes(' ')) {
|
||||
return trimmed.split(' ')[0];
|
||||
}
|
||||
}
|
||||
return formatDateValue(value);
|
||||
};
|
||||
|
||||
// 获取负责人名称
|
||||
const getOwnerNames = (memberList) => {
|
||||
if (!Array.isArray(memberList) || memberList.length === 0) return '未分配';
|
||||
|
|
@ -518,6 +585,15 @@ const getAvatarText = (member) => {
|
|||
};
|
||||
|
||||
const deletingProjectId = ref('');
|
||||
const showStartModal = ref(false);
|
||||
const startingProject = ref(false);
|
||||
const startProjectForm = reactive({
|
||||
id: '',
|
||||
expectedCompleteDate: ''
|
||||
});
|
||||
const currentStartProjectName = ref('');
|
||||
const startDatePickerRef = ref(null);
|
||||
const startDatePickerValue = ref(Date.now());
|
||||
|
||||
// 处理卡片菜单
|
||||
const handleCardMenu = (project) => {
|
||||
|
|
@ -532,13 +608,86 @@ const handleCardMenu = (project) => {
|
|||
// 新增任务
|
||||
uni.showToast({ title: '新增任务功能开发中', icon: 'none' });
|
||||
} else if (res.tapIndex === 3) {
|
||||
// 开始开发
|
||||
uni.showToast({ title: '开始开发功能开发中', icon: 'none' });
|
||||
handleStartDevelopment(project);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleStartDevelopment = (project) => {
|
||||
if (!project?.id) {
|
||||
uni.showToast({
|
||||
title: '缺少项目ID',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
startProjectForm.id = project.id;
|
||||
startProjectForm.expectedCompleteDate = extractDateOnly(project.expectedCompleteDate || project.expireTime || '');
|
||||
currentStartProjectName.value = project.name || project.projectName || '';
|
||||
showStartModal.value = true;
|
||||
};
|
||||
|
||||
const closeStartModal = () => {
|
||||
resetStartForm();
|
||||
showStartModal.value = false;
|
||||
};
|
||||
|
||||
const resetStartForm = () => {
|
||||
startProjectForm.id = '';
|
||||
startProjectForm.expectedCompleteDate = '';
|
||||
currentStartProjectName.value = '';
|
||||
};
|
||||
|
||||
const submitStartDevelopment = async () => {
|
||||
if (!startProjectForm.id) {
|
||||
uni.showToast({
|
||||
title: '缺少项目ID',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!startProjectForm.expectedCompleteDate) {
|
||||
uni.showToast({
|
||||
title: '请选择预计完成日期',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
startingProject.value = true;
|
||||
await startProjectDevelopment({
|
||||
id: startProjectForm.id,
|
||||
expectedCompleteDate: startProjectForm.expectedCompleteDate
|
||||
});
|
||||
uni.showToast({ title: '已开始开发', icon: 'success' });
|
||||
closeStartModal();
|
||||
await refresh();
|
||||
} catch (err) {
|
||||
console.error('开始开发失败:', err);
|
||||
uni.showToast({
|
||||
title: err?.message || '操作失败,请稍后重试',
|
||||
icon: 'none'
|
||||
});
|
||||
} finally {
|
||||
startingProject.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const openStartDatePicker = () => {
|
||||
startDatePickerValue.value = startProjectForm.expectedCompleteDate
|
||||
? new Date(startProjectForm.expectedCompleteDate.replace(/-/g, '/')).getTime()
|
||||
: Date.now();
|
||||
if (startDatePickerRef.value?.open) {
|
||||
startDatePickerRef.value.open();
|
||||
}
|
||||
};
|
||||
|
||||
const onStartDateConfirm = (event) => {
|
||||
if (!event?.value) return;
|
||||
startProjectForm.expectedCompleteDate = formatDateValue(event.value);
|
||||
};
|
||||
|
||||
const handleDeleteProject = (project) => {
|
||||
if (!project?.id) {
|
||||
uni.showToast({
|
||||
|
|
@ -1078,5 +1227,99 @@ onLoad(() => {
|
|||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.start-modal {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.modal-mask {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.modal-panel {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 86%;
|
||||
max-width: 360px;
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 16px;
|
||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.modal-close {
|
||||
font-size: 18px;
|
||||
color: #999;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.modal-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.modal-subtitle {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.field-label {
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.date-input {
|
||||
height: 40px;
|
||||
border-radius: 8px;
|
||||
background: #f5f6f7;
|
||||
padding: 0 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.date-input .placeholder {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.date-icon {
|
||||
font-size: 16px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user