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