From a7ac91bc5ae3c2ce0badca1ae9fc7ed57af95758 Mon Sep 17 00:00:00 2001 From: riku <risaku@163.com> Date: 星期二, 22 十月 2024 15:15:28 +0800 Subject: [PATCH] 1. 添加子任务编辑功能(暂存) --- src/api/fysp/subtaskApi.js | 12 + src/components.d.ts | 6 src/views/fysp/task/components/CompSubTaskEdit.vue | 157 ++++++++++++++++++++++ src/components/list-item/ItemSubTask.vue | 152 +++++++++++++++++--- src/views/fysp/task/components/CompSubTaskList.vue | 73 ++++++++- src/views/fysp/task/TaskManage.vue | 2 6 files changed, 358 insertions(+), 44 deletions(-) diff --git a/src/api/fysp/subtaskApi.js b/src/api/fysp/subtaskApi.js new file mode 100644 index 0000000..972f307 --- /dev/null +++ b/src/api/fysp/subtaskApi.js @@ -0,0 +1,12 @@ +import { $fysp } from '../index'; + +export default { + /** + * 璋冩暣瀛愪换鍔′俊鎭� + * @param {Object} subtask + * @returns + */ + adjustSubtask(subtask){ + return $fysp.post(`subtask/adjust`, subtask).then((res) => res.data); + }, +}; diff --git a/src/components.d.ts b/src/components.d.ts index 12178e1..37e7435 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -19,7 +19,6 @@ ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] ElButton: typeof import('element-plus/es')['ElButton'] - ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] ElCalendar: typeof import('element-plus/es')['ElCalendar'] ElCard: typeof import('element-plus/es')['ElCard'] ElCascader: typeof import('element-plus/es')['ElCascader'] @@ -48,11 +47,7 @@ ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup'] ElOption: typeof import('element-plus/es')['ElOption'] - ElPageHeader: typeof import('element-plus/es')['ElPageHeader'] - ElPagination: typeof import('element-plus/es')['ElPagination'] ElPopover: typeof import('element-plus/es')['ElPopover'] - ElRadioButton: typeof import('element-plus/es')['ElRadioButton'] - ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] ElRow: typeof import('element-plus/es')['ElRow'] ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] ElSegmented: typeof import('element-plus/es')['ElSegmented'] @@ -67,6 +62,7 @@ ElTabs: typeof import('element-plus/es')['ElTabs'] ElTag: typeof import('element-plus/es')['ElTag'] ElText: typeof import('element-plus/es')['ElText'] + ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTree: typeof import('element-plus/es')['ElTree'] ElUpload: typeof import('element-plus/es')['ElUpload'] Footer: typeof import('./components/core/Footer.vue')['default'] diff --git a/src/components/list-item/ItemSubTask.vue b/src/components/list-item/ItemSubTask.vue index 210bebc..ac1f3ab 100644 --- a/src/components/list-item/ItemSubTask.vue +++ b/src/components/list-item/ItemSubTask.vue @@ -1,36 +1,68 @@ <template> <div class="wrapper"> - <div class="text-title"> - {{ item.name }} - </div> - <div class="text-info"> - <div class="text-label"> - <el-icon class="m-r-4" size="16"><LocationInformation /></el-icon> - <span>浠诲姟鍦板潃锛�</span> - </div> - {{ item.scenseaddress }} - </div> - <div class="text-info"> - <div class="text-label"> - <!-- <el-icon><Clock /></el-icon> --> - <el-icon class="m-r-4" size="16"><AlarmClock /></el-icon> - <span>浠诲姟鏃堕棿锛�</span> - </div> - {{ $fm.formatYMD(item.planstarttime) }} - </div> - <div class="text-info"> - <div class="text-label"> - <el-icon class="m-r-4" size="16"><User /></el-icon> - 浠诲姟浜哄憳锛� - </div> - {{ item.executorrealtimes }} - </div> - <el-row justify="end" style="margin-top: 4px"> - <slot :item="item"></slot> + <el-row justify="space-between" class="m-t-4"> + <el-col :span="20"> + <div class="text-title"> + <el-tag + size="small" + :type="statusType.type" + effect="plain" + class="m-r-4 m-b-4" + > + <el-space :size="4"> + <el-icon size="16"> + <component :is="statusType.icon"></component> + </el-icon> + {{ item.status }} + </el-space> + </el-tag> + {{ item.name }} + </div> + <div class="text-info"> + <div class="text-label"> + <el-icon class="m-r-4" size="16"><LocationInformation /></el-icon> + <span>浠诲姟鍦板潃锛�</span> + </div> + {{ item.scenseaddress }} + </div> + <div class="text-info"> + <div class="text-label"> + <!-- <el-icon><Clock /></el-icon> --> + <el-icon class="m-r-4" size="16"><AlarmClock /></el-icon> + <span>浠诲姟鏃堕棿锛�</span> + </div> + {{ $fm.formatYMD(item.planstarttime) }} + </div> + <div class="text-info"> + <div class="text-label"> + <el-icon class="m-r-4" size="16"><User /></el-icon> + 浠诲姟浜哄憳锛� + </div> + {{ item.executorrealtimes }} + </div> + <el-space class="m-t-4"> + <el-tag size="small" type="info" effect="" + >闂锛歿{ status.proNum }}</el-tag + > + <el-tag size="small" type="info" effect="" + >鏁存敼锛歿{ status.changeNum }}</el-tag + > + <el-tag size="small" :type="changePerType" effect="" + >鏁存敼鐜囷細{{ status.changePer }}</el-tag + > + </el-space> + </el-col> + <el-col :span="4"> + <slot :item="item"></slot> + </el-col> </el-row> </div> </template> <script setup> +import { ref, watch, computed } from 'vue'; +import taskApi from '@/api/fysp/taskApi'; +import ProCheckProxy from '@/views/fysp/check/ProCheckProxy'; + /** * 鐩戠瀵硅薄 */ @@ -40,6 +72,72 @@ default: () => {} } }); + +const loading = ref(false); +const proList = ref([]); +const status = ref({}); + +const statusType = computed(() => { + switch (props.item.status) { + case '鏈墽琛�': + return { + type: 'danger', + icon: 'WarningFilled' + }; + case '姝e湪鎵ц': + return { + type: 'success', + icon: 'Timer' + }; + case '宸茬粨鏉�': + return { + type: 'info', + icon: 'SuccessFilled' + }; + default: + return { + type: 'danger', + icon: 'Warning' + }; + } +}); + +const changePerType = computed(() => { + if (status.value.changeNum == 0) { + if (status.value.proNum == 0) { + return 'success'; + } else { + return 'danger'; + } + } else if (status.value.proNum == status.value.changeNum) { + return 'success'; + } else { + return 'warning'; + } +}); + +watch( + () => props.item, + (nV, oV) => { + if (nV != oV) { + fetchProblems(nV); + } + }, + { immediate: true } +); + +function fetchProblems(subtask) { + loading.value = true; + taskApi + .getProBySubtask(subtask.stguid) + .then((res) => { + proList.value = res; + status.value = ProCheckProxy.calProStatus(res); + }) + .finally(() => { + loading.value = false; + }); +} </script> <style scoped> .wrapper { diff --git a/src/views/fysp/task/TaskManage.vue b/src/views/fysp/task/TaskManage.vue index a3e4f21..8940905 100644 --- a/src/views/fysp/task/TaskManage.vue +++ b/src/views/fysp/task/TaskManage.vue @@ -48,7 +48,7 @@ <el-col v-if="curSubTaskList" :span="8"> <CompSubTaskList create - :data="curSubTaskList" + v-model="curSubTaskList" :loading="subTaskLoading" height="56vh" @add="subTaskDrawer = true" diff --git a/src/views/fysp/task/components/CompSubTaskEdit.vue b/src/views/fysp/task/components/CompSubTaskEdit.vue new file mode 100644 index 0000000..a7d6f47 --- /dev/null +++ b/src/views/fysp/task/components/CompSubTaskEdit.vue @@ -0,0 +1,157 @@ +<template> + <FYForm + :form-info="formInfo" + :rules="rules" + :useCancel="true" + @submit="submit" + @cancel="cancel" + > + <template #form-item="{ formObj }"> + <el-form-item label="浠诲姟鍚嶇О" prop="name"> + <el-input disabled v-model="formObj.name" placeholder="浠诲姟鍚嶇О" /> + </el-form-item> + <el-form-item label="鍦烘櫙鍦板潃" prop="name"> + <el-input + disabled + v-model="formObj.scenseaddress" + placeholder="鍦烘櫙鍦板潃" + /> + </el-form-item> + <FYOptionTime + label="璁″垝鏃堕棿" + prop="planstarttime" + :initValue="false" + type="date" + v-model:value="formObj.planstarttime" + ></FYOptionTime> + <el-form-item label="鎵ц浜�" prop="_executors"> + <el-select + v-model="formObj._executors" + multiple + clearable + collapse-tags + placeholder="閫夋嫨鎵ц浜�" + :max-collapse-tags="3" + style="width: 300px" + > + <el-option + v-for="s in executorOptions" + :key="s.value" + :label="s.label" + :value="s.value" + /> + </el-select> + </el-form-item> + </template> + </FYForm> +</template> +<script setup> +import { ref, computed, onMounted, reactive } from 'vue'; +import subtaskApi from '@/api/fysp/subtaskApi'; +import userApi from '@/api/fysp/userApi'; + +const props = defineProps({ + //鍩烘湰淇℃伅 + modelValue: Object, + //鏄垱寤烘垨鑰呮洿鏂� + create: Boolean +}); + +const emit = defineEmits(['submit', 'cancel']); + +// 浠诲姟鎵ц浜洪�夐」 +const executorOptions = ref([]); +const formInfo = computed(() => { + return { + ...props.modelValue, + _executors: props.modelValue + ? props.modelValue.executorguids.split('#') + : [] + }; +}); + +const rules = reactive({ + name: [ + { + required: true, + message: '鍦烘櫙鍚嶇О涓嶈兘涓虹┖', + trigger: 'blur' + } + ], + _scenetype: [ + { + required: true, + message: '鍦烘櫙绫诲瀷涓嶈兘涓虹┖', + trigger: 'change' + } + ] +}); + +function getExecutors(data) { + const ids = []; + const uNames = []; + const rNames = []; + executorOptions.value.forEach((e) => { + const index = data._executors.indexOf(e.value); + if (index != -1) { + ids.push(e.data.guid); + uNames.push(e.data.acountname); + rNames.push(e.data.realname); + } + }); + return { + id: ids.join('#'), + uName: uNames.join('#'), + rName: rNames.join('#') + }; +} + +// 鍒涘缓鏂板満鏅� +function createScene(v, success, fail) { + // return sceneApi + // .createScene(v) + // .then(() => { + // emit('onSubmit', v); + // success(); + // }) + // .catch((err) => { + // fail(err); + // }); +} +// 鏇存柊鍦烘櫙 +function updateScene(v, success, fail) { + return subtaskApi + .adjustSubtask(v) + .then(() => { + emit('submit', v); + success(); + }) + .catch((err) => { + fail(err); + }); +} +function submit(v, success, fail) { + return props.create + ? createScene(v.value, success, fail) + : updateScene(v.value, success, fail); +} +function cancel() { + emit('cancel'); +} + +function initOptions() { + userApi.getUserByType(1).then((res) => { + executorOptions.value = res.map((v) => { + return { + label: v.realname, + value: v.guid, + data: v + }; + }); + }); +} + +onMounted(() => { + initOptions(); +}); +</script> diff --git a/src/views/fysp/task/components/CompSubTaskList.vue b/src/views/fysp/task/components/CompSubTaskList.vue index b84adbd..b678652 100644 --- a/src/views/fysp/task/components/CompSubTaskList.vue +++ b/src/views/fysp/task/components/CompSubTaskList.vue @@ -2,7 +2,7 @@ <el-row justify="space-between"> <el-text>鍗曟棩璁″垝</el-text> <el-button - v-show="create && data && data.length > 0" + v-show="create && modelValue && modelValue.length > 0" type="success" size="small" @click="add" @@ -13,17 +13,26 @@ <div> <el-scrollbar v-loading="loading" :height="height"> <el-space - v-if="data && data.length > 0" + v-if="modelValue && modelValue.length > 0" fill :fill-ratio="100" direction="vertical" style="width: 100%" > - <ItemSubTask v-for="s in data" :key="s.guid" :item="s"> + <ItemSubTask v-for="s in modelValue" :key="s.guid" :item="s"> <template #default="{ item }"> - <el-button type="danger" size="small" @click="remove(item)" - >绉婚櫎</el-button - > + <el-space direction="vertical"> + <el-button plain type="primary" size="small" @click="edit(item)" + >缂栬緫</el-button + > + <el-button + :disabled="item.status != '鏈墽琛�'" + type="default" + size="small" + @click="remove(item)" + >绉婚櫎</el-button + > + </el-space> </template> </ItemSubTask> </el-space> @@ -37,12 +46,29 @@ </div> </el-scrollbar> </div> + <el-dialog + v-model="dialogVisible" + width="600" + title="涓�閿垱寤烘�讳换鍔�" + destroy-on-close + :close-on-click-modal="false" + :close-on-press-escape="false" + :show-close="false" + > + <CompSubTaskEdit + v-model="activeItem" + @submit="dialogVisible = false" + @cancel="dialogVisible = false" + ></CompSubTaskEdit> + </el-dialog> </template> <script setup> -import { ref, watch, onMounted } from 'vue'; +import { ref, computed, watch, onMounted, onUnmounted } from 'vue'; +import { ElMessageBox, ElNotification, ElMessage } from 'element-plus'; +import CompSubTaskEdit from './CompSubTaskEdit.vue'; const props = defineProps({ - data: Array, + modelValue: Array, height: { type: String, default: '70vh' @@ -51,15 +77,40 @@ create: Boolean, loading: Boolean }); -const curSubTaskList = ref([]); -const emit = defineEmits(['add', 'remove']); +const dialogVisible = ref(false) +const activeItem = ref(null) +const data = computed(() => props.modelValue); + +const emit = defineEmits(['edit', 'add', 'remove', 'update:modelValue']); function remove(item) { - emit('remove', item); + if (item.status == '鏈墽琛�') { + ElMessageBox.confirm('鏄惁绉婚櫎鐩戠浠诲姟', `绉婚櫎纭`, { + confirmButtonText: '纭', + cancelButtonText: '鍙栨秷', + type: 'warning' + }).then(() => { + const index = data.value.indexOf(item); + data.value.splice(index, 1); + + emit('update:modelValue', data.value); + emit('remove', item); + }); + } +} + +function edit(item) { + activeItem.value = item + dialogVisible.value = true + emit('edit'); } function add() { emit('add'); } + +onUnmounted(()=>{ + dialogVisible.value = false +}) </script> -- Gitblit v1.9.3