Переглянути джерело

Merge remote-tracking branch 'origin/master'

Hwf 7 місяців тому
батько
коміт
adcd8adb2a

+ 27 - 0
src/api/emergencyCommandMap/JointDuty.ts

@@ -117,4 +117,31 @@ export function getTaskList(params) {
     method: "get",
     params: params
   });
+}
+
+// 请示领导
+export function addLeaderRequest(data) {
+  return request({
+    url: "/api/taskRegistration/leader_request",
+    method: "post",
+    data: data
+  });
+}
+
+// 任务反馈
+export function addFeeback(data) {
+  return request({
+    url: "/api/taskRegistration/feeback",
+    method: "post",
+    data: data
+  });
+}
+
+// 任务详情
+export function getTaskDetail(params) {
+  return request({
+    url: "/api/taskRegistration/detail",
+    method: 'get',
+    params: params
+  });
 }

+ 9 - 0
src/router/routes.ts

@@ -278,6 +278,15 @@ export const constantRoutes: Array<RouteRecordRaw> = [
     meta: {
       title: "采集结果"
     }
+  },
+  {
+    path: "/taskFeebackDetail",
+    name: "taskFeebackDetail",
+    component: () =>
+      import("@/views/worker/eventManagement/taskFeebackDetail.vue"),
+    meta: {
+      title: "任务详情"
+    }
   }
 ];
 

+ 145 - 0
src/views/worker/eventManagement/feebackDialog.vue

@@ -0,0 +1,145 @@
+<template>
+    <van-popup v-model:show="visible">
+        <van-form @submit="on_submit">
+            <div class="van-doc-block__title">任务反馈</div>
+            <van-cell-group inset>
+                <van-field
+                    v-model="form.feeback_user"
+                    label="反馈人:"
+                    placeholder="默认当前登录用户"
+                    :rules="[{ required: false, message: '请填写反馈人'  }]"
+                />
+
+                <van-field
+                    v-model="form.processing_status"
+                    is-link
+                    readonly
+                    label="事件等级"
+                    placeholder="选择事件等级"
+                    @click="show_processing_status_picker = true"
+                />
+                
+                <div style="font-size:14px;color:var(--van-field-label-color);margin-top:10px;padding-left: 15px;">反馈内容:</div>
+                <van-field
+                    required
+                    v-model="form.content"
+                    placeholder="请填写反馈内容"
+                    :rules="[{ required: true, message: '请填写反馈内容'  }]"
+                    rows="3"
+                    autosize
+                    type="textarea"
+                    maxlength="150"
+                    show-word-limit
+                />
+
+                <van-field name="fileList" label="照片/视频" label-align="top">
+                    <template #input>
+                        <ImageUpload v-model="form.fileList" :fileType="['png', 'jpeg', 'jpg']"/>
+                    </template>
+                </van-field>
+                
+            </van-cell-group>
+            <div style="margin: 3.0vmin;display: flex;
+                flex-direction: row;
+                justify-content: flex-end;">
+                <div style="display: flex;        flex-direction: row;  justify-content: space-between;">
+                    <van-button @click="closeDialog(false)" style="margin-right:10px;">取 消</van-button>
+                    <van-button type="primary" native-type="submit">确 定</van-button>
+                </div>
+            </div>
+        </van-form>    
+    </van-popup>
+
+    <van-popup v-model:show="show_processing_status_picker" round position="bottom">
+        <van-picker
+            :columns="opt_processing_status"
+            @cancel="show_processing_status_picker = false"
+            @confirm="on_processing_status_confirm"
+        />
+    </van-popup>
+    
+</template>
+
+<script lang="ts" setup>
+import { getCurrentInstance, ref, watch, defineEmits } from 'vue';
+import { addFeeback } from '@/api/emergencyCommandMap/JointDuty';
+import { showSuccessToast } from 'vant';
+
+const proxy = getCurrentInstance()?.proxy;
+
+const opt_processing_status = [
+    { text: '处理中', value: '处理中' },
+    { text: '已完成', value: '已完成' }
+];
+
+interface Form {
+    task_id: string;
+    content: string;
+    processing_status: string;
+    feeback_type: string;
+    feeback_user: string;
+    fileList: any;
+}
+interface Props {
+    modelValue: boolean;
+    data: Form;
+}
+
+const form = ref<Form>({
+    task_id: "",
+    content: "",
+    processing_status: "",
+    feeback_type: "",
+    feeback_user: "",
+    fileList: []
+});
+
+const props = withDefaults(defineProps<Props>(), {
+  modelValue: false
+});
+
+const emits = defineEmits(['update:modelValue']);
+watch(
+  () => props.modelValue,
+  () => {
+    if (props.modelValue) {
+      form.value = props.data;
+    }
+    visible.value = props.modelValue;
+  }
+);
+
+const visible = ref(false);
+const show_processing_status_picker = ref(false)
+
+const on_processing_status_confirm = ({ selectedOptions }) => {
+    console.log(selectedOptions[0]);
+    show_processing_status_picker.value = false;
+    form.value.processing_status = selectedOptions[0].text;
+};
+
+const on_submit = () => {
+    console.log('on_submit');
+    addFeeback(form.value).then((res) => {
+        showSuccessToast(res.msg);
+        closeDialog(true)
+    }).catch((err) => {
+    });
+};
+
+const closeDialog = (t) => {
+  emits('update:modelValue', t);
+};
+
+</script>
+
+<style lang="scss" scoped>
+.van-doc-block__title {
+    color: var(--van-doc-text-color-4);
+    margin: 0px;
+    padding: 3vmin;
+    font-size: 4.6vmin;
+    font-weight: 600;
+    line-height: 6.0vmin;
+}
+</style>

+ 113 - 0
src/views/worker/eventManagement/requestDialog.vue

@@ -0,0 +1,113 @@
+<template>
+    <van-popup v-model:show="visible">
+        <van-form @submit="on_submit">
+            <div class="van-doc-block__title">请示领导</div>
+            <van-cell-group inset>
+                <van-field
+                    v-model="form.leader_unit"
+                    label="领导单位:"
+                    placeholder="请选择领导所属单位名称"
+                    :rules="[{ required: true, message: '请选择领导所属单位名称'  }]"
+                />
+                <van-field
+                    v-model="form.leader_name"
+                    label="领导姓名:"
+                    placeholder="请选择领导姓名"
+                    :rules="[{ required: true, message: '请选择领导姓名'  }]"
+                />
+                <div style="font-size:14px;color:var(--van-field-label-color);margin-top:10px;padding-left: 15px;">请示信息:</div>
+                <van-field
+                    required
+                    v-model="form.content"
+                    placeholder="请填写请示信息"
+                    :rules="[{ required: true, message: '请填写请示信息'  }]"
+                    rows="3"
+                    autosize
+                    type="textarea"
+                    maxlength="150"
+                    show-word-limit
+                />
+            </van-cell-group>
+            <div style="margin: 3.0vmin;display: flex;
+                flex-direction: row;
+                justify-content: flex-end;">
+                <div style="display: flex;        flex-direction: row;  justify-content: space-between;">
+                    <van-button @click="closeDialog(false)" style="margin-right:10px;">取 消</van-button>
+                    <van-button type="primary" native-type="submit">确 定</van-button>
+                </div>
+            </div>
+        </van-form>    
+    </van-popup>
+</template>
+
+<script lang="ts" setup>
+import { getCurrentInstance, ref, watch, defineEmits } from 'vue';
+import { addLeaderRequest } from '@/api/emergencyCommandMap/JointDuty';
+import { showSuccessToast } from 'vant';
+
+const proxy = getCurrentInstance()?.proxy;
+
+interface Form {
+    task_id: string;
+    content: string;
+    processing_status: string;
+    feeback_type: string;
+    leader_unit: string;
+    leader_name: string;
+}
+interface Props {
+    modelValue: boolean;
+    data: Form;
+}
+
+const form = ref<Form>({
+    task_id: "",
+    content: "",
+    processing_status: "",
+    feeback_type: "",
+    leader_unit: "",
+    leader_name: ""
+});
+
+const props = withDefaults(defineProps<Props>(), {
+  modelValue: false
+});
+
+const emits = defineEmits(['update:modelValue']);
+watch(
+  () => props.modelValue,
+  () => {
+    if (props.modelValue) {
+      form.value = props.data;
+    }
+    visible.value = props.modelValue;
+  }
+);
+
+const visible = ref(false);
+
+const on_submit = () => {
+    console.log('on_submit');
+    addLeaderRequest(form.value).then((res) => {
+        showSuccessToast(res.msg);
+        closeDialog(true)
+    }).catch((err) => {
+    });
+};
+
+const closeDialog = (t) => {
+  emits('update:modelValue', t);
+};
+
+</script>
+
+<style lang="scss" scoped>
+.van-doc-block__title {
+    color: var(--van-doc-text-color-4);
+    margin: 0px;
+    padding: 3vmin;
+    font-size: 4.6vmin;
+    font-weight: 600;
+    line-height: 6.0vmin;
+}
+</style>

+ 188 - 0
src/views/worker/eventManagement/taskFeebackDetail.vue

@@ -0,0 +1,188 @@
+<template>
+    <div class="container">
+        <div class="event-list-item">
+            <div class="item-content">
+                <div class="item-data">
+                    <div class="item-left">
+                        <div class="item-data-label">任务类型:</div>
+                    </div>
+                    <div class="item-data-value">{{ get_task_type_text(task_info.task_type) }}</div>
+                </div>
+                <div class="item-data">
+                    <div class="item-left">
+                        <div class="item-data-label">关键事件:</div>
+                    </div>
+                    <div class="item-data-value">{{ task_info.event_name }}</div>
+                </div>
+                <div class="item-data">
+                    <div class="item-left">
+                        <div class="item-data-label">任务状态:</div>
+                    </div>
+                    <div class="item-data-value">{{ task_info.processing_status }}</div>
+                </div>
+                <div class="item-data">
+                    <div class="item-left">
+                        <div class="item-data-label">要求完成时间:</div>
+                    </div>
+                    <div class="item-data-value">{{ task_info.expire_time || "-"  }}</div>
+                </div>
+                <div class="item-data" v-show="task_info.processing_status == '已完成'">
+                    <div class="item-left">
+                        <div class="item-data-label">实际完成时间:</div>
+                    </div>
+                    <div class="item-data-value">{{ task_info.update_time }}</div>
+                </div>
+                <div class="item-data">
+                    <div class="item-left">
+                        <div class="item-data-label">反馈人:</div>
+                    </div>
+                    <div class="item-data-value">{{ task_info.feeback_user || "-" }}</div>
+                </div>
+                <div class="item-data">
+                    <div class="item-left">
+                        <div class="item-data-label">任务信息:</div>
+                    </div>
+                </div>
+                <div class="item-data">
+                    <div class="item-data-content">{{ task_info.task_description}}</div>
+                </div>
+            </div>
+
+            <div class="item-content"
+                v-for="(item, index) in task_info.feebacks"
+                :key="item.id">
+                <div class="item-data">
+                    <div class="item-left">
+                        <div class="item-data-label">反馈内容:</div>
+                    </div>
+                    <div class="item-data-value">{{ item.create_time || "-" }}</div>
+                </div>
+                <div class="item-data">
+                    <div class="item-data-content">{{ item.content}}</div>
+                </div>
+                <div class="item-data" v-if="item.fileCount > 0">
+                <div class="item-left">
+                    <div class="item-data-label">照片/视频:</div>
+                </div>
+                <div class="item-data-image" v-if="item.fileCount > 0">
+                    <img
+                        v-for="(file, _) in item.fileList"
+                        :key="file.id"
+                        class="image"
+                        :src="get_img_url(file.url)"
+                    ></img>
+                </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</template>
+
+<script lang="ts" setup>
+import {reactive, ref, toRefs, onMounted} from 'vue';
+import {useRoute, useRouter} from "vue-router";
+import { getTaskDetail } from '@/api/emergencyCommandMap/JointDuty';
+import { showToast } from 'vant';
+const route = useRoute();
+const task_id = ref('');
+const data = reactive({
+    task_info: {
+        task_type: '',
+        event_name: '',
+        processing_status: '',
+        expire_time: '',
+        update_time: '',
+        feeback_user : '',
+        task_description: '',
+        feebacks: []
+    }
+});
+const { task_info } = toRefs(data);
+
+const opt_task_type = [
+    { text: "全部", value: "" },
+    { text: "事件处置", value: "0" },
+    { text: "防范措施", value: "1" },
+    { text: "险情处理", value: "2" },
+    { text: "督办任务", value: "3" }
+];
+
+const get_task_type_text = (val) => {
+    return opt_task_type.find(item => item.value == val).text
+}
+
+const baseUrl = import.meta.env.VITE_BASE_API;
+const downLoadApi = import.meta.env.VITE_BASE_DOWNLOAD_API;
+
+const get_img_url = (url) => {
+  return baseUrl + downLoadApi + url;
+}
+
+onMounted(()=> {
+    task_id.value = route.query.task_id as string || "";
+    getTaskDetail({task_id: task_id.value}).then((res)=>{
+        task_info.value = res.data;
+    })
+})
+</script>
+
+
+<style lang="scss" scoped>
+.container {
+    background: #ffffff;
+    padding: 8px 0 ;
+
+.event-list-item {
+    position: relative;
+    margin: 8px 8px 0;
+    // background: #ffffff;
+    // border-radius: 4px;
+    // border: 0.5px solid #eaedf7;
+    // box-shadow: 0 0 4px 0 #4554661a;
+    &:first-child {
+      margin-top: 0px;
+    }
+    .item-content {
+      padding: 0 12px 12px;
+    }
+    .item-data {
+      font-size: 14px;
+      display: flex;
+      flex-direction: row;
+      align-items: flex-start;
+      justify-content: space-between;
+      line-height: 26px;
+      .item-left {
+        display: flex;
+        align-items: center;
+        flex-shrink: 0;
+      }
+      .item-data-label {
+        flex-shrink: 0;
+        color: #414f64;
+        font-weight: 600;
+      }
+  
+      .item-data-value {
+        color: #414f64;
+      }
+
+      .item-data-content {
+        background: #f1f1f1;
+        padding:4px 8px;
+      }
+
+      .item-data-image {
+        display:flex;
+        flex-direction: row; 
+
+        .image {
+          height:var(--van-uploader-size);;
+          width:var(--van-uploader-size);;
+        }
+      }
+    }
+}
+}
+</style>

+ 81 - 4
src/views/worker/eventManagement/taskList.vue

@@ -74,23 +74,38 @@
           <div class="item-bottom" v-else>
             <van-button
               type="primary"
-              @click="handleFeedback(index)"
+              @click="handleFeedbackDetail(index)"
             >
               查看反馈
             </van-button>
           </div>
         </div>
       </van-list>
+
+      <RequestDialog
+        v-model="requestDialogState.show"
+        :data="requestDialogState.form"
+        @update:model-value="onRequestDialogClose"
+      />
+
+      <FeebackDialog
+        v-model="feebackDialogState.show"
+        :data="feebackDialogState.form"
+        @update:model-value="onFeebackDialogClose"
+      />
     </div>
   </template>
   
   <script lang="ts" setup>
-  import { getCurrentInstance, ref} from "vue";
+  import { getCurrentInstance, ref, reactive} from "vue";
   import { useRouter } from "vue-router";
   import { getTaskList } from '@/api/emergencyCommandMap/JointDuty';
   import searchImg from "@/assets/images/search.png";
   import closeImg from "@/assets/images/close.png";
   
+  import RequestDialog from "./requestDialog.vue";
+  import FeebackDialog from "./feebackDialog.vue";
+
   const proxy = getCurrentInstance()?.proxy;
   //const { mm_event_type, mm_event_level, mm_event_state } = toRefs<any>(
   //  proxy?.useDict("mm_event_type", "mm_event_level", "mm_event_state")
@@ -179,16 +194,78 @@
         loading.value = false;
       });
   };
+
+  // 请求请示对话框
+  const requestDialogState = reactive({
+    show: false,
+    form: {
+      task_id: "",
+      content: "",
+      processing_status: "",
+      feeback_type: "1",
+      leader_unit: "",
+      leader_name: ""
+    }
+  });
+
+  const onRequestDialogClose = t => {
+    requestDialogState.show = false;
+    console.log(requestDialogState.form);
+    if (t) {
+      queryParams.value.page = 0;
+      getList();
+    }
+  };
   
   const handleRequest = (index) => {
     current_item.value = task_list.value[index];
-    //router.push("/event/detail?event_id=" + current_item.value.event_id+"&nocontrol=1");
+    console.log('handleRequest:', current_item.value);
+    requestDialogState.form.task_id = current_item.value.task_id;
+    requestDialogState.form.processing_status = current_item.value.processing_status;
+    requestDialogState.form.leader_unit = "";
+    requestDialogState.form.leader_name = "";
+    requestDialogState.form.content = "";
+    requestDialogState.show = true;
+  };
+
+  // 任务反馈对话框
+
+  const feebackDialogState = reactive({
+    show: false,
+    form: {
+      task_id: "",
+      content: "",
+      processing_status: "",
+      feeback_type: "0",
+      feeback_user: '',
+      fileList: []
+    }
+  });
+
+  const onFeebackDialogClose = t => {
+    feebackDialogState.show = false;
+    console.log(feebackDialogState.form);
+    if (t) {
+      queryParams.value.page = 0;
+      getList();
+    }
   };
 
   const handleFeedback = (index) => {
     current_item.value = task_list.value[index];
-    //router.push("/event/detail?event_id=" + current_item.value.event_id+"&nocontrol=1");
+    console.log('handleFeedback:', current_item.value);
+    feebackDialogState.form.task_id = current_item.value.task_id;
+    feebackDialogState.form.processing_status = current_item.value.processing_status;
+    feebackDialogState.form.content = "";
+    feebackDialogState.form.fileList = [];
+    feebackDialogState.show = true;
   };
+
+  const handleFeedbackDetail = (index) => {
+    current_item.value = task_list.value[index];
+    console.log('handleFeedbackDetail:', current_item.value);
+    router.push("/taskFeebackDetail?task_id=" + current_item.value.task_id);
+  }
   </script>
   
   <style lang="scss" scoped>