Sfoglia il codice sorgente

Merge remote-tracking branch 'origin/master'

Hwf 7 mesi fa
parent
commit
407eaf62ea

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

@@ -144,4 +144,22 @@ export function getTaskDetail(params) {
     method: 'get',
     params: params
   });
+}
+
+// 请示列表
+export function getRequestList(params) {
+  return request({
+    url: "/api/taskRegistration/request/list",
+    method: 'get',
+    params: params
+  });
+}
+
+// 请示批复(提交)
+export function addApproval(data) {
+  return request({
+    url: "/api/taskRegistration/approval",
+    method: "post",
+    data: data
+  });
 }

+ 2 - 2
src/router/routes.ts

@@ -311,7 +311,7 @@ export const leaderRoute: Array<RouteRecordRaw> = [
         name: "MobileControl",
         component: () => import("@/views/mobileControl/index.vue"),
         meta: {
-          title: "移动指挥(平时态)",
+          title: "移动指挥",
           noCache: true
         }
       },
@@ -376,7 +376,7 @@ export const workerRoute = [
         name: "MobileControl",
         component: () => import("@/views/mobileControl/index.vue"),
         meta: {
-          title: "移动指挥(平时态)",
+          title: "移动指挥",
           noCache: true
         }
       },

+ 95 - 0
src/views/worker/eventManagement/approvalDialog.vue

@@ -0,0 +1,95 @@
+<!-- 请示批复 -->
+<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
+                    required
+                    v-model="form.approval_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 { addApproval } from '@/api/emergencyCommandMap/JointDuty';
+import { showSuccessToast } from 'vant';
+
+const proxy = getCurrentInstance()?.proxy;
+
+interface Form {
+    feeback_id: string;
+    approval_content: string;
+}
+interface Props {
+    modelValue: boolean;
+    data: Form;
+}
+
+const form = ref<Form>({
+    feeback_id: "",
+    approval_content: ""
+});
+
+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');
+    addApproval(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>

+ 2 - 4
src/views/worker/eventManagement/index.vue

@@ -9,9 +9,7 @@
       <div class="content">
         <eventList v-if="activeIndex === 'event'" @changIndex="handleClickTab" />
         <taskList v-else-if="activeIndex === 'task'" />
-        <!--
-        <investigationRecords v-else-if="activeIndex === 'job'" />
-      -->
+        <requestlist v-else-if="activeIndex === 'job'" />
       </div>
     </div>
   </template>
@@ -19,7 +17,7 @@
   import { ref } from "vue";
   import eventList from "./eventList.vue";
   import taskList from "./taskList.vue";
-  //import dangerousSource from "./dangerousSource.vue";
+  import requestlist from "./requestList.vue";
 
   let activeIndex = ref('event');
   let tabs = ref([

+ 394 - 0
src/views/worker/eventManagement/requestList.vue

@@ -0,0 +1,394 @@
+<template>
+    <div class="container">
+      <!--搜索框-->
+      <van-search
+        v-model="queryParams.search_keyword"
+        class="common-search"
+        placeholder="请输入请示内容"
+        :left-icon="searchImg"
+        :right-icon="closeImg"
+        :clearable="false"
+        @search="on_search_keyword"
+        @click-right-icon.stop="on_search_cancel"
+      />
+      <!-- 两个类型选择 -->
+      <van-dropdown-menu>
+        <van-dropdown-item
+          v-model="queryParams.task_type"
+          :title="!!queryParams.task_type ? '' : '类型'"
+          :options="opt_task_type"
+          @change="change_task_type"
+        />
+        <van-dropdown-item
+          v-model="queryParams.processing_status"
+          :title="!!queryParams.processing_status ? '' : '状态'"
+          :options="opt_processing_status"
+          @change="change_processing_status"
+        />
+      </van-dropdown-menu>
+  
+      <van-list
+        v-model:loading="loading"
+        v-model:error="error"
+        error-text="请求失败,点击重新加载"
+        :finished="finished"
+        finished-text="没有更多请示了"
+        class="list"
+        @load="getList"
+      >
+        <div
+          v-for="(item, index) in task_list"
+          :key="item.id"
+          class="event-list-item"
+        >
+          <div class="item-title">
+            <div class="task_type">工作请示</div>
+            <div class="item-title-text" style="color: #2c81ff;" v-if="item.event_name != ''" @click="handleTaskDetail(index)">查看任务详情</div>
+          </div>
+          <div class="item-status">
+            <div class="task_status">{{item.nick_name}}</div>
+            <div class="task_status">{{item.processing_status}}</div>
+            <!--  
+            <div class="task_status">{{item.update_time}}</div>
+            -->
+          </div>
+          <div class="item-content">
+            {{ item.content || "暂无请示内容"}}
+          </div>
+          <div class="item-bottom" v-if="item.processing_status != '已完成'">
+            <van-button
+              type="primary"
+              @click="handleApproval(index)"
+            >
+              请示批复
+            </van-button>
+          </div>
+          <div class="item-bottom" v-else>
+            <van-button
+              type="primary"
+              @click="handleFeedbackDetail(index)"
+            >
+              查看批复
+            </van-button>
+          </div>
+        </div>
+      </van-list>
+
+      <RequestDialog
+        v-model="requestDialogState.show"
+        :data="requestDialogState.form"
+        @update:model-value="onRequestDialogClose"
+      />
+
+      <ApprovalDialog
+        v-model="approvalDialogState.show"
+        :data="approvalDialogState.form"
+        @update:model-value="onApprovalDialogClose"
+      />
+      <div class="float-box" @click="handleRequestAdd">新建请示</div>
+    </div>
+  </template>
+  
+  <script lang="ts" setup>
+  import { getCurrentInstance, ref, reactive} from "vue";
+  import { useRouter } from "vue-router";
+  import { getRequestList } from '@/api/emergencyCommandMap/JointDuty';
+  import searchImg from "@/assets/images/search.png";
+  import closeImg from "@/assets/images/close.png";
+  
+  import RequestDialog from "./requestDialog.vue";
+  import ApprovalDialog from "./approvalDialog.vue";
+
+  const proxy = getCurrentInstance()?.proxy;
+  
+  const router = useRouter();
+  
+  const opt_task_type = [
+    { text: "全部", value: "" },
+    { text: "事件处置", value: "0" },
+    { text: "防范措施", value: "1" },
+    { text: "险情处理", value: "2" },
+    { text: "督办任务", value: "3" }
+  ];
+  
+  const opt_processing_status = [
+    { text: "全部", value: "" },
+    { text: "处理中", value: "处理中" },
+    { text: "已完成", value: "已完成" }
+  ];
+  
+  const current_item = ref(null);
+  const task_list = ref([]);
+  const total = ref(0);
+  const loading = ref(false);
+  const error = ref(false);
+  const finished = ref(false);
+  const queryParams = ref({
+    page: 0,
+    page_size: 10,
+    task_type: "",
+    processing_status: "",
+    search_keyword: ""
+  });
+  
+  const on_search_keyword = val => {
+    queryParams.value.search_keyword = val;
+    queryParams.value.page = 0;
+    getList();
+  };
+  
+  const on_search_cancel = () => {
+    queryParams.value.search_keyword = "";
+    queryParams.value.page = 0;
+    getList();
+  };
+  
+  const change_task_type = () => {
+    queryParams.value.page = 0;
+    getList();
+  };
+
+  const change_processing_status = () => {
+    queryParams.value.page = 0;
+    getList();
+  };
+  
+  const getList = () => {
+    queryParams.value.page++;
+    getRequestList(queryParams.value)
+      .then(res => {
+        var items = res.data || [];
+        total.value = res.total;
+        if (queryParams.value.page == 1) {
+            task_list.value = [];
+        }
+        items.forEach(val => {
+            task_list.value.push(val);
+        });
+        if (queryParams.value.page_size * queryParams.value.page >= total.value) {
+          finished.value = true;
+        } else {
+          finished.value = false;
+        }
+      })
+      .catch(() => {
+        error.value = true;
+        finished.value = false;
+      })
+      .finally(() => {
+        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 handleRequestAdd = () => {
+    requestDialogState.form.task_id = "";
+    requestDialogState.form.processing_status = "处理中";
+    requestDialogState.form.leader_unit = "";
+    requestDialogState.form.leader_name = "";
+    requestDialogState.form.content = "";
+    requestDialogState.show = true;
+  }
+
+  // 请示批复对话框
+
+  const approvalDialogState = reactive({
+    show: false,
+    form: {
+      feeback_id: "",
+      approval_content: ""
+    }
+  });
+
+  const onApprovalDialogClose = t => {
+    approvalDialogState.show = false;
+    console.log(approvalDialogState.form);
+    if (t) {
+      queryParams.value.page = 0;
+      getList();
+    }
+  };
+
+  const handleApproval = (index) => {
+    current_item.value = task_list.value[index];
+    console.log('handleApproval:', current_item.value);
+    approvalDialogState.form.feeback_id = current_item.value.id;
+    approvalDialogState.form.approval_content = "";
+    approvalDialogState.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);
+  }
+
+  const handleTaskDetail = (index)=> {
+    current_item.value = task_list.value[index];
+    router.push("/taskFeebackDetail?task_id=" + current_item.value.task_id);
+  }
+
+  
+  </script>
+  
+  <style lang="scss" scoped>
+  .list {
+    height: calc(100vh - 102px);
+    overflow-y: auto;
+  }
+  .van-doc-block__title {
+    color: var(--van-doc-text-color-4);
+    margin: 0;
+    padding: 32px 16px 16px;
+    font-size: 14px;
+    font-weight: 400;
+    line-height: 16px;
+  }
+  
+  .event-list-item {
+    position: relative;
+    margin: 16px 16px 0;
+    background: #ffffff;
+    border-radius: 4px;
+    border: 0.5px solid #eaedf7;
+    box-shadow: 0 0 4px 0 #4554661a;
+    &:first-child {
+      margin-top: 0;
+    }
+    .item-title {
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      min-height: 46px;
+      background-image: linear-gradient(180deg, #f3f7fd 0%, #ffffff 100%);
+      padding: 0 12px;
+      .item-title-text {
+        font-size: 14px;
+        color: #414f64;
+      }
+  
+      .item-title-control {
+        display: inline-flex;
+        justify-content: center;
+        align-items: center;
+      }
+      .van-button {
+        width: 73px;
+        height: 24px;
+        padding: 0;
+      }
+
+      .task_type {
+            font-size: 14px;
+            padding: 3px 10px;
+            color:#fff;
+            background: #2c81ff;
+        }
+    }
+
+    .item-status {
+        font-size: 14px;
+        display: flex;
+        flex-direction: row;
+        align-items: flex-start;
+        justify-content: start;
+        line-height: 20px;
+        padding: 0 12px 12px;
+        
+        .task_status {
+            padding: 2px 8px;
+            color: #414f64;
+            background: #ccc;
+            border: 0.8px solid #999;
+            border-radius: 2px;
+            margin-right:10px;
+            max-width: 220px;
+            white-space: nowrap;
+            text-overflow: ellipsis;
+            overflow: hidden;
+        }
+    }
+    .item-content {
+      padding: 0 12px 12px;
+      font-size: 14px;
+      color: #414f64;
+    }
+
+    .item-bottom {
+        display: flex;
+        align-items: center;
+        justify-content: flex-end;
+
+        .van-button {
+            width: 76px;
+            height: 30px;
+            padding: 0;
+            margin-right: 16px;
+            margin-bottom: 16px;
+            }
+    }
+  }
+  .van-dropdown-menu {
+    :deep(.van-dropdown-menu__bar) {
+      background: transparent;
+      box-shadow: none;
+    }
+  }
+  .common-search {
+    :deep(.van-field__left-icon) {
+      .van-icon__image {
+        width: 12px;
+        height: 12px;
+      }
+    }
+    :deep(.van-field__right-icon) {
+      width: 30px;
+      height: 30px;
+      padding: 0;
+      .van-icon__image {
+        width: 30px;
+        height: 30px;
+      }
+    }
+  }
+
+  // 新建请示浮动按钮
+.float-box {
+  position: fixed;
+  right: 10px;
+  bottom: 70px;
+  width: 86px;
+  height: 77px;
+  background: url("@/assets/images/event/float.png") no-repeat;
+  background-size: 100% 100%;
+  display: flex;
+  align-items: flex-end;
+  color: #fff;
+  padding-left: 5px;
+  padding-bottom: 3px;
+  font-size: 16px;
+}
+  </style>
+  

+ 45 - 22
src/views/worker/eventManagement/taskFeebackDetail.vue

@@ -48,30 +48,53 @@
                 </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 class="item-content" v-for="(item, index) in task_info.feebacks" :key="item.id">
+                <div data-type="任务反馈" v-if="item.feeback_type == '0'">
+                    <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 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 data-type="领导批示" v-if="item.feeback_type == '1'">
+                    <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">
+                        <div class="item-left">
+                            <div class="item-data-label">批复内容:</div>
+                        </div>
+                        <div class="item-data-value">{{ item.approval_time}}</div>
+                    </div>
+                    <div class="item-data">
+                        <div class="item-data">
+                            <div class="item-data-content">{{ item.approval_content || "未批复"}}</div>
+                        </div>
+                    </div>
                 </div>
             </div>