From f1f26b166b71371e0a8dfaf9b9f575d2d79feefc Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期三, 23 四月 2025 17:40:03 +0800
Subject: [PATCH] 完成线索任务的发布功能

---
 src/constant/response-level.js                       |   26 +
 src/components/search-option/OptionLocation.vue      |  164 ++++++++
 src/components/search-option/OptionTravelMode.vue    |   42 ++
 src/api/clue/clueTaskApi.js                          |   33 +
 src/model/clueQuestion.js                            |    4 
 src/components.d.ts                                  |    6 
 src/views/overlay-clue/report/ClueReport.vue         |   45 ++
 src/api/fysp/userApi.js                              |   48 ++
 src/views/overlay-clue/list/ClueManage.vue           |    7 
 src/api/index.js                                     |   35 +
 src/components/search-option/OptionExecutors.vue     |   69 +++
 src/constant/travel-mode.js                          |   22 +
 src/views/overlay-clue/task/ClueTaskEdit.vue         |  289 +++++++++++++++
 src/components/search-option/OptionResponseLevel.vue |   42 ++
 src/constant/location.js                             |  257 +++++++++++++
 src/views/overlay-clue/ClueLayout.vue                |    5 
 src/views/overlay-clue/list/components/ClueList.vue  |   13 
 17 files changed, 1,082 insertions(+), 25 deletions(-)

diff --git a/src/api/clue/clueTaskApi.js b/src/api/clue/clueTaskApi.js
new file mode 100644
index 0000000..bd52d71
--- /dev/null
+++ b/src/api/clue/clueTaskApi.js
@@ -0,0 +1,33 @@
+import { $clue } from '../index';
+
+export default {
+  /**
+   * 鍒涘缓绾跨储浠诲姟
+   * @param {*} clueTask
+   * @returns
+   */
+  createClueTask(clueTask) {
+    return $clue
+      .put(`clue/task/create`, clueTask)
+  },
+
+  /**
+   * 鏇存柊绾跨储浠诲姟
+   * @param {*} clueTask
+   * @returns
+   */
+  updateClueTask(clueTask) {
+    return $clue
+      .post(`clue/task/update`, clueTask)
+  },
+
+  /**
+   * 鏌ヨ绾跨储浠诲姟
+   * @param {*} clueTask
+   * @returns
+   */
+  fetchClueTask(clueTask) {
+    return $clue
+      .post(`clue/task/fetch`, clueTask)
+  }
+};
diff --git a/src/api/fysp/userApi.js b/src/api/fysp/userApi.js
new file mode 100644
index 0000000..022c9be
--- /dev/null
+++ b/src/api/fysp/userApi.js
@@ -0,0 +1,48 @@
+import { $fysp } from '../index';
+
+export default {
+  /**
+   * 鑾峰彇鐢ㄦ埛璇︽儏
+   */
+  getUserById(id) {
+    return $fysp.get(`userinfo/${id}`).then((res) => res.data);
+  },
+
+  /**
+   * 鏇存柊鐢ㄦ埛璇︽儏
+   */
+  updateUser(user) {
+    return $fysp.post(`userinfo`, user).then((res) => res.data);
+  },
+
+  /**
+   * 鑾峰彇鍦烘櫙鐨勭敤鎴疯鎯�
+   */
+  getUserByScene(sId) {
+    return $fysp
+      .get(`userinfo/scene/get?sceneId=${sId}`)
+      .then((res) => res.data);
+  },
+
+  /**
+   * 鑷姩鍒涘缓璐︽埛
+   */
+  autoCreateAccount(sId) {
+    return $fysp.post(`userinfo/create?sceneId=${sId}`).then((res) => res.data);
+  },
+  /**
+   * 鑾峰彇鍦烘櫙瀵瑰簲鐨勯缇界幆澧冪郴缁熺敤鎴穒d
+   */
+  getTzId(sceneId) {
+    return $fysp.get(`usermap?sceneId=${sceneId}`).then((res) => res.data);
+  },
+
+  /**
+   * 鎸夌敤鎴风被鍨嬭幏鍙栫敤鎴蜂俊鎭�
+   */
+  getUserByType(typeId, enable = true) {
+    return $fysp
+      .get(`userinfo/type/get`, { params: { typeId, enable } })
+      .then((res) => res.data);
+  }
+};
diff --git a/src/api/index.js b/src/api/index.js
index 8c92e9a..f88ce35 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -1,17 +1,37 @@
 import axios from 'axios';
 import { setInterceptors } from "./config";
 
-// const url = 'http://47.100.191.150:9031/';
-const url = 'http://192.168.0.110:8084/';
-// const imgUrl = 'http://47.100.191.150:9031/images/';
-const imgUrl = 'http://192.168.0.110:8084/images/';
+const debug = true;
+
+// let url1 = 'http://47.100.191.150:9031/';
+// let url1_file = 'http://47.100.191.150:9031';
+let url1 = 'https://fyami.com.cn:448/';
+let url1_file = 'https://fyami.com.cn:448/';
+let url2 = 'http://47.100.191.150:9005/';
+let url2_file = 'http://47.100.191.150:9005/';
+
+if (debug) {
+  url1 = 'http://192.168.0.110:8084/';
+  url1_file = 'http://192.168.0.110:8084/';
+  // url2 = 'http://192.168.0.110:9001/';
+  // url2_file = 'http://192.168.0.138:8080/';
+}
 
 //椋炵窘鐩戠
 const $clue = axios.create({
-  baseURL: url,
-  timeout: 10000
+  baseURL: url1,
+  timeout: 20000
   // headers: addHeaders()
 });
+$clue.imgUrl = `${url1_file}images/`;
+
+//椋炵窘鐩戠
+const $fysp = axios.create({
+  baseURL: url2,
+  timeout: 20000
+});
+$fysp.imgUrl = `${url2_file}images/`;
+$fysp.downloadUrl = `${url2_file}files/`;
 
 // function getHeaders() {
 //   const token = 'e6dc8bb9e1ff0ce973fb92b4af2e4c3f';
@@ -30,5 +50,6 @@
 
 //娣诲姞鎷︽埅鍣�
 setInterceptors($clue)
+setInterceptors($fysp)
 
-export { $clue, imgUrl };
+export { $clue, $fysp };
diff --git a/src/components.d.ts b/src/components.d.ts
index 85ce2c9..692e2b1 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -13,6 +13,7 @@
     DescriptionsList: typeof import('./components/list/DescriptionsList.vue')['default']
     DescriptionsListItem: typeof import('./components/list/DescriptionsListItem.vue')['default']
     ElButton: typeof import('element-plus/es')['ElButton']
+    ElCascader: typeof import('element-plus/es')['ElCascader']
     ElCol: typeof import('element-plus/es')['ElCol']
     ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
     ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
@@ -33,11 +34,16 @@
     ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSpace: typeof import('element-plus/es')['ElSpace']
+    ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     MapSearch: typeof import('./components/map/MapSearch.vue')['default']
+    OptionExecutors: typeof import('./components/search-option/OptionExecutors.vue')['default']
+    OptionLocation: typeof import('./components/search-option/OptionLocation.vue')['default']
+    OptionResponseLevel: typeof import('./components/search-option/OptionResponseLevel.vue')['default']
     OptionTime: typeof import('./components/search-option/OptionTime.vue')['default']
+    OptionTravelMode: typeof import('./components/search-option/OptionTravelMode.vue')['default']
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
   }
diff --git a/src/components/search-option/OptionExecutors.vue b/src/components/search-option/OptionExecutors.vue
new file mode 100644
index 0000000..f69e7cb
--- /dev/null
+++ b/src/components/search-option/OptionExecutors.vue
@@ -0,0 +1,69 @@
+<template>
+  <el-select
+    :model-value="modelValue"
+    @update:model-value="handleChange"
+    multiple
+    clearable
+    placeholder="閫夋嫨鎵ц浜�"
+    class="w-300"
+  >
+    <el-option
+      v-for="(s, i) in executorOptions"
+      :key="i"
+      :label="s.label"
+      :value="s.value"
+    />
+  </el-select>
+</template>
+
+<script>
+/**
+ * 绾跨储浠诲姟鎵ц浜洪�夐」
+ */
+import userApi from '@/api/fysp/userApi';
+export default {
+  props: {
+    modelValue: {
+      type: Array,
+      default: () => []
+    },
+    userType: {
+      type: Number,
+      default: 1
+    }
+  },
+  emits: ['update:modelValue', 'initOver'],
+  data() {
+    return {
+      executorOptions: []
+    };
+  },
+  methods: {
+    getOptions() {
+      return userApi.getUserByType(this.userType).then((res) => {
+        res.forEach((v) => {
+          this.executorOptions.push({
+            label: v.realname,
+            value: v.guid
+            // data: v
+          });
+        });
+        // this.executorOptions = res.map((v) => {
+        //   return {
+        //     label: v.realname,
+        //     value: v.guid
+        //     // data: v
+        //   };
+        // });
+      });
+    },
+    handleChange(value) {
+      this.$emit('update:modelValue', value);
+    }
+  },
+  mounted() {
+    this.getOptions().finally(() => this.$emit('initOver'));
+    // this.handleChange(this.pollutionList[0].value);
+  }
+};
+</script>
diff --git a/src/components/search-option/OptionLocation.vue b/src/components/search-option/OptionLocation.vue
new file mode 100644
index 0000000..403099a
--- /dev/null
+++ b/src/components/search-option/OptionLocation.vue
@@ -0,0 +1,164 @@
+<template>
+  <!-- <el-form-item :label="placeholder" :prop="prop"> -->
+  <el-cascader
+    :model-value="formatedValue"
+    @change="handleChange"
+    :options="locations"
+    :placeholder="placeholder"
+    :props="optionProps"
+    :style="'width: ' + width + 'px'"
+  />
+  <!-- </el-form-item> -->
+</template>
+
+<script>
+import { enumLocation } from '@/constant/location';
+
+export default {
+  props: {
+    // 鏄惁鍦ㄩ閫夐」澶勬坊鍔犫�滃叏閮ㄢ�濋�夐」
+    allOption: {
+      type: Boolean,
+      default: true
+    },
+    // 鏌ヨ鐨勮鏀跨骇鍒紝鍙栧��1锛�2锛�3锛�4, 5, 6
+    level: {
+      type: Number,
+      default: 4
+    },
+    // 缁撴灉杩斿洖
+    modelValue: Object,
+    // 鏄惁榛樿杩斿洖鍒濆閫夐」
+    initValue: {
+      type: Boolean,
+      default: true
+    },
+    // 鑳藉惁閫夋嫨浠绘剰涓�绾ч�夐」
+    checkStrictly: {
+      type: Boolean,
+      default: true
+    },
+    prop: {
+      type: String,
+      default: '_locations'
+    },
+    width: {
+      type: Number,
+      default: 220
+    }
+  },
+  emits: ['update:modelValue'],
+  data() {
+    return {
+      locations: enumLocation(this.allOption, this.level),
+      optionProps: {
+        checkStrictly: this.checkStrictly
+      }
+    };
+  },
+  computed: {
+    placeholder() {
+      const list = '鐪�/甯�/鍖�/闀�/闆�/鐗�'.split('/');
+      const p = [];
+      for (let i = 0; i < this.level; i++) {
+        p.push(list[i]);
+      }
+      return p.join('/');
+    },
+    formatedValue() {
+      return this.optionFormatReverse(this.modelValue);
+    }
+  },
+  methods: {
+    handleChange(value) {
+      this.$emit('update:modelValue', this.optionFormat(value));
+    },
+    /**
+     * 鍦板尯閫夐」缁撴灉鏍煎紡鍖�
+     */
+    optionFormat(val) {
+      const res = {
+        pCode: null,
+        pName: null,
+        cCode: null,
+        cName: null,
+        dCode: null,
+        dName: null,
+        tCode: null,
+        tName: null,
+        aCode: null,
+        aName: null,
+        mCode: null,
+        mName: null
+      };
+      if (val.length > 0) {
+        res.pCode = val[0][0];
+        res.pName = val[0][1];
+      }
+      if (val.length > 1) {
+        res.cCode = val[1][0];
+        res.cName = val[1][1];
+      }
+      if (val.length > 2) {
+        res.dCode = val[2][0];
+        res.dName = val[2][1];
+      }
+      if (val.length > 3) {
+        res.tCode = val[3][0];
+        res.tName = val[3][1];
+      }
+      if (val.length > 4) {
+        res.aCode = val[4][0];
+        res.aName = val[4][1];
+      }
+      if (val.length > 5) {
+        res.mCode = val[5][0];
+        res.mName = val[5][1];
+      }
+      return res;
+    },
+    optionFormatReverse(val) {
+      const res = [];
+      if (val) {
+        if (val.pName) {
+          res.push([val.pCode, val.pName]);
+        }
+        if (val.cName) {
+          res.push([val.cCode, val.cName]);
+        }
+        if (val.dName) {
+          res.push([val.dCode, val.dName]);
+        }
+        if (val.tName) {
+          res.push([val.tCode, val.tName]);
+        }
+        if (val.aName) {
+          res.push([val.aCode, val.aName]);
+        }
+        if (val.mName) {
+          res.push([val.mCode, val.mName]);
+        }
+      }
+      return res;
+    }
+  },
+  mounted() {
+    if (this.initValue) {
+      if (this.checkStrictly) {
+        this.handleChange([this.locations[0].value]);
+      } else {
+        const f = (location) => {
+          if (location.children && location.children.length > 0) {
+            const r = f(location.children[0]);
+            r.unshift(location.value);
+            return r;
+          } else {
+            return [location.value];
+          }
+        };
+        this.handleChange(f(this.locations[0]));
+      }
+    }
+  }
+};
+</script>
diff --git a/src/components/search-option/OptionResponseLevel.vue b/src/components/search-option/OptionResponseLevel.vue
new file mode 100644
index 0000000..d4fb7b2
--- /dev/null
+++ b/src/components/search-option/OptionResponseLevel.vue
@@ -0,0 +1,42 @@
+<template>
+  <el-select
+    :model-value="modelValue"
+    @update:model-value="handleChange"
+    placeholder="鍝嶅簲绾у埆"
+    class="w-120"
+  >
+    <el-option
+      v-for="(s, i) in responseLevelList"
+      :key="i"
+      :label="s.label"
+      :value="s.value"
+    />
+  </el-select>
+</template>
+
+<script>
+/**
+ * 绾跨储浠诲姟鍝嶅簲绾у埆閫夐」
+ */
+import { responseLevelList } from '@/constant/response-level';
+export default {
+  props: {
+    modelValue: String
+  },
+  emits: ['update:modelValue', 'initOver'],
+  data() {
+    return {
+      responseLevelList: responseLevelList()
+    };
+  },
+  methods: {
+    handleChange(value) {
+      this.$emit('update:modelValue', value);
+    }
+  },
+  mounted() {
+    this.$emit('initOver');
+    // this.handleChange(this.pollutionList[0].value);
+  }
+};
+</script>
diff --git a/src/components/search-option/OptionTravelMode.vue b/src/components/search-option/OptionTravelMode.vue
new file mode 100644
index 0000000..b79c880
--- /dev/null
+++ b/src/components/search-option/OptionTravelMode.vue
@@ -0,0 +1,42 @@
+<template>
+  <el-select
+    :model-value="modelValue"
+    @update:model-value="handleChange"
+    placeholder="鍑鸿鏂瑰紡"
+    class="w-120"
+  >
+    <el-option
+      v-for="(s, i) in travelModeList"
+      :key="i"
+      :label="s.label"
+      :value="s.value"
+    />
+  </el-select>
+</template>
+
+<script>
+/**
+ * 绾跨储浠诲姟鍑鸿鏂瑰紡閫夐」
+ */
+import { travelModeList } from '@/constant/travel-mode';
+export default {
+  props: {
+    modelValue: String
+  },
+  emits: ['update:modelValue', 'initOver'],
+  data() {
+    return {
+      travelModeList: travelModeList()
+    };
+  },
+  methods: {
+    handleChange(value) {
+      this.$emit('update:modelValue', value);
+    }
+  },
+  mounted() {
+    this.$emit('initOver');
+    // this.handleChange(this.pollutionList[0].value);
+  }
+};
+</script>
diff --git a/src/constant/location.js b/src/constant/location.js
new file mode 100644
index 0000000..cf4054c
--- /dev/null
+++ b/src/constant/location.js
@@ -0,0 +1,257 @@
+/**
+ * 鑾峰彇琛屾斂鍖哄垝
+ * @param {Boolean} allOption 鏄惁鍦ㄥご閮ㄦ坊鍔犫�滃叏閮ㄢ�濋�夐」
+ * @param {Number} level 鑾峰彇鐨勫垎绫绘繁搴︼紝鑼冨洿 1 - 4
+ * @returns
+ */
+function enumLocation(allOption = true, level = 4) {
+  const l = _enumLocation();
+  if (!allOption) {
+    l.shift();
+  }
+  _deleteByLevel(l, level, 1);
+
+  return l;
+}
+
+function _enumLocation() {
+  return [
+    {
+      label: '鍏ㄥ競',
+      value: [null, '鍏ㄥ競']
+    },
+    {
+      label: '涓婃捣甯�',
+      value: ['31', '涓婃捣甯�'],
+      children: [
+        {
+          label: '涓婃捣甯�',
+          value: ['3100', '涓婃捣甯�'],
+          children: [
+            {
+              label: '閲戝北鍖�',
+              value: ['310116', '閲戝北鍖�'],
+              children: [
+                { label: '寮犲牥闀�', value: ['310116103', '寮犲牥闀�'] },
+                { label: '浜灄闀�', value: ['310116104', '浜灄闀�'] },
+                { label: '鍚曞贩闀�', value: ['310116105', '鍚曞贩闀�'] },
+                { label: '寤婁笅闀�', value: ['310116107', '寤婁笅闀�'] },
+                { label: '楂樻柊鍖�', value: ['310116503', '楂樻柊鍖�'] },
+                { label: '閲戝北鍗晣', value: ['310116109', '閲戝北鍗晣'] },
+                { label: '婕曟尘闀�', value: ['310116112', '婕曟尘闀�'] },
+                {
+                  label: '灞遍槼闀�',
+                  value: ['310116113', '灞遍槼闀�'],
+                  children: [
+                    {
+                      label: '涓囪揪骞垮満',
+                      value: ['31011611301', '涓囪揪骞垮満']
+                    }
+                  ]
+                },
+                { label: '鐭冲寲琛楅亾', value: ['310116001', '鐭冲寲琛楅亾'] },
+                { label: '鏈辨尘闀�', value: ['310116101', '鏈辨尘闀�'] },
+                { label: '鏋尘闀�', value: ['310116102', '鏋尘闀�'] },
+                { label: '纰宠胺缁挎咕', value: ['9000', '纰宠胺缁挎咕'] }
+              ]
+            },
+            {
+              label: '寰愭眹鍖�',
+              value: ['310104', '寰愭眹鍖�'],
+              children: [
+                {
+                  label: '婕曟渤娉炬柊鍏存妧鏈紑鍙戝尯',
+                  value: ['310104501', '婕曟渤娉炬柊鍏存妧鏈紑鍙戝尯']
+                },
+                { label: '婀栧崡璺閬�', value: ['310104004', '婀栧崡璺閬�'] },
+                { label: '澶╁钩璺閬�', value: ['310104003', '澶╁钩璺閬�'] },
+                { label: '铏规璺閬�', value: ['310104012', '铏规璺閬�'] },
+                { label: '鏋灄璺閬�', value: ['310104008', '鏋灄璺閬�'] },
+                { label: '鏂滃湡璺閬�', value: ['310104007', '鏂滃湡璺閬�'] },
+                { label: '闀挎ˉ琛楅亾', value: ['310104010', '闀挎ˉ琛楅亾'] },
+                {
+                  label: '鐢版灄琛楅亾',
+                  value: ['310104011', '鐢版灄琛楅亾'],
+                  children: [
+                    {
+                      label: '鐢板皻鍧�',
+                      value: ['31010401101', '鐢板皻鍧�']
+                    }
+                  ]
+                },
+                { label: '搴峰仴鏂版潙琛楅亾', value: ['310104013', '搴峰仴鏂版潙琛楅亾'] },
+                {
+                  label: '寰愬姹囪閬�',
+                  value: ['310104014', '寰愬姹囪閬�'],
+                  children: [
+                    {
+                      label: '澶╅挜妗�',
+                      value: ['31010401401', '澶╅挜妗�']
+                    }
+                  ]
+                },
+                { label: '鍑屼簯璺閬�', value: ['310104015', '鍑屼簯璺閬�'] },
+                { label: '榫欏崕琛楅亾', value: ['310104016', '榫欏崕琛楅亾'] },
+                { label: '婕曟渤娉捐閬�', value: ['310104017', '婕曟渤娉捐閬�'] },
+                { label: '鍗庢尘闀�', value: ['310104103', '鍗庢尘闀�'] }
+              ]
+            },
+            {
+              label: '闈欏畨鍖�',
+              value: ['310106', '闈欏畨鍖�'],
+              children: [
+                {
+                  label: '澶у畞璺閬�',
+                  value: ['310106019', '澶у畞璺閬�'],
+                  children: [
+                    {
+                      label: '涔呭厜涓績',
+                      value: ['31010601901', '涔呭厜涓績']
+                    }
+                  ]
+                },
+                { label: '褰郸鏂版潙琛楅亾', value: ['310106020', '褰郸鏂版潙琛楅亾'] },
+                { label: '涓存本璺閬�', value: ['310106021', '涓存本璺閬�'] },
+                { label: '鑺锋睙瑗胯矾琛楅亾', value: ['310106022', '鑺锋睙瑗胯矾琛楅亾'] },
+                {
+                  label: '褰郸闀�',
+                  value: ['310106101', '褰郸闀�'],
+                  children: [
+                    {
+                      label: '澶ц瀺鍩�',
+                      value: ['31010610101', '澶ц瀺鍩�']
+                    }
+                  ]
+                },
+                { label: '姹熷畞璺閬�', value: ['310106006', '姹熷畞璺閬�'] },
+                { label: '鐭抽棬浜岃矾琛楅亾', value: ['310106011', '鐭抽棬浜岃矾琛楅亾'] },
+                {
+                  label: '鍗椾含瑗胯矾琛楅亾',
+                  value: ['310106012', '鍗椾含瑗胯矾琛楅亾'],
+                  children: [
+                    {
+                      label: 'X88',
+                      value: ['31010601201', 'X88']
+                    }
+                  ]
+                },
+                { label: '闈欏畨瀵鸿閬�', value: ['310106013', '闈欏畨瀵鸿閬�'] },
+                {
+                  label: '鏇瑰娓¤閬�',
+                  value: ['310106014', '鏇瑰娓¤閬�'],
+                  children: [
+                    {
+                      label: '889',
+                      value: ['31010601401', '889']
+                    }
+                  ]
+                },
+                { label: '澶╃洰瑗胯矾琛楅亾', value: ['310106015', '澶╃洰瑗胯矾琛楅亾'] },
+                {
+                  label: '鍖楃珯琛楅亾',
+                  value: ['310106016', '鍖楃珯琛楅亾'],
+                  children: [
+                    {
+                      label: '澶ф偊鍩�',
+                      value: ['31010601601', '澶ф偊鍩�']
+                    }
+                  ]
+                },
+                { label: '瀹濆北璺閬�', value: ['310106017', '瀹濆北璺閬�'] },
+                { label: '鍏卞拰鏂拌矾琛楅亾', value: ['310106018', '鍏卞拰鏂拌矾琛楅亾'] }
+              ]
+            },
+            {
+              label: '鏅檧鍖�',
+              value: ['310107', '鏅檧鍖�'],
+              children: [
+                { label: '鏇规潹鏂版潙琛楅亾', value: ['310107005', '鏇规潹鏂版潙琛楅亾'] },
+                { label: '涓囬噷琛楅亾', value: ['310107021', '涓囬噷琛楅亾'] },
+                { label: '鐪熷闀囪閬�', value: ['310107022', '鐪熷闀囪閬�'] },
+                { label: '闀垮緛闀�', value: ['310107102', '闀垮緛闀�'] },
+                { label: '妗冩郸闀�', value: ['310107103', '妗冩郸闀�'] },
+                { label: '鐭虫硥璺閬�', value: ['310107017', '鐭虫硥璺閬�'] },
+                { label: '鐢樻硥璺閬�', value: ['310107016', '鐢樻硥璺閬�'] },
+                { label: '闀垮璺閬�', value: ['310107015', '闀垮璺閬�'] },
+                { label: '闀块鏂版潙琛楅亾', value: ['310107014', '闀块鏂版潙琛楅亾'] },
+                { label: '瀹滃窛璺閬�', value: ['310107020', '瀹滃窛璺閬�'] }
+              ]
+            },
+            {
+              label: '闂佃鍖�',
+              value: ['310112', '闂佃鍖�'],
+              children: [
+                { label: '姹熷窛璺閬�', value: ['310112001', '姹熷窛璺閬�'] },
+                { label: '鍙ょ編琛楅亾', value: ['310112006', '鍙ょ編琛楅亾'] },
+                { label: '鏂拌櫣琛楅亾', value: ['310112008', '鏂拌櫣琛楅亾'] },
+                { label: '娴﹂敠琛楅亾', value: ['310112009', '娴﹂敠琛楅亾'] },
+                { label: '鑾樺簞闀�', value: ['310112101', '鑾樺簞闀�'] },
+                { label: '涓冨疂闀�', value: ['310112102', '涓冨疂闀�'] },
+                { label: '棰涙ˉ闀�', value: ['310112103', '棰涙ˉ闀�'] },
+                { label: '鍗庢紩闀�', value: ['310112106', '鍗庢紩闀�'] },
+                { label: '铏规ˉ闀�', value: ['310112107', '铏规ˉ闀�'] },
+                { label: '姊呴檱闀�', value: ['310112108', '姊呴檱闀�'] },
+                { label: '鍚存尘闀�', value: ['310112110', '鍚存尘闀�'] },
+                { label: '椹ˉ闀�', value: ['310112112', '椹ˉ闀�'] },
+                { label: '娴︽睙闀�', value: ['310112114', '娴︽睙闀�'] },
+                { label: '鑾樺簞宸ヤ笟鍖�', value: ['310112501', '鑾樺簞宸ヤ笟鍖�'] }
+              ]
+            },
+            {
+              label: '闀垮畞鍖�',
+              value: ['310105', '闀垮畞鍖�'],
+              children: [
+                { label: '鍗庨槼璺閬�', value: ['310105001', '鍗庨槼璺閬�'] },
+                { label: '姹熻嫃璺閬�', value: ['310105002', '姹熻嫃璺閬�'] },
+                { label: '鏂板崕璺閬�', value: ['310105004', '鏂板崕璺閬�'] },
+                { label: '鍛ㄥ妗ヨ閬�', value: ['310105005', '鍛ㄥ妗ヨ閬�'] },
+                { label: '澶╁北璺閬�', value: ['310105006', '澶╁北璺閬�'] },
+                { label: '浠欓湠鏂版潙琛楅亾', value: ['310105008', '浠欓湠鏂版潙琛楅亾'] },
+                { label: '铏规ˉ琛楅亾', value: ['310105009', '铏规ˉ琛楅亾'] },
+                { label: '绋嬪妗ヨ閬�', value: ['310105010', '绋嬪妗ヨ閬�'] },
+                { label: '鍖楁柊娉捐閬�', value: ['310105011', '鍖楁柊娉捐閬�'] },
+                { label: '鏂版尘闀�', value: ['310105102', '鏂版尘闀�'] }
+              ]
+            },
+            {
+              label: '瀹濆北鍖�',
+              value: ['310113', '瀹濆北鍖�'],
+              children: []
+            },
+            {
+              label: '鍢夊畾鍖�',
+              value: ['310114', '鍢夊畾鍖�'],
+              children: []
+            },
+            {
+              label: '娴︿笢鏂板尯',
+              value: ['310115', '娴︿笢鏂板尯'],
+              children: []
+            }
+          ]
+        }
+      ]
+    }
+  ];
+}
+
+// 鎸夌収闇�姹傜殑瀹氫綅绮惧害杩斿洖瀵瑰簲鏁版嵁
+function _deleteByLevel(locations, level, step) {
+  if (step == level) {
+    locations.forEach((l) => {
+      if (l.children) {
+        l.children = undefined;
+      }
+    });
+    return;
+  } else {
+    step++;
+    locations.forEach((l) => {
+      if (l.children) {
+        _deleteByLevel(l.children, level, step);
+      }
+    });
+  }
+}
+
+export { enumLocation };
diff --git a/src/constant/response-level.js b/src/constant/response-level.js
new file mode 100644
index 0000000..3f9cf8e
--- /dev/null
+++ b/src/constant/response-level.js
@@ -0,0 +1,26 @@
+function responseLevelList() {
+  return [
+    {
+      label: '褰撴棩',
+      value: 0
+    },
+    {
+      label: '涓夊ぉ鍐�',
+      value: 1
+    },
+    {
+      label: '涓�鍛ㄥ唴',
+      value: 2
+    },
+    {
+      label: '褰撴湀',
+      value: 3
+    },
+  ];
+}
+
+function responseLevelName(type) {
+  return responseLevelList().find((v) => v.value == type).label;
+}
+
+export { responseLevelList, responseLevelName };
diff --git a/src/constant/travel-mode.js b/src/constant/travel-mode.js
new file mode 100644
index 0000000..6b931ce
--- /dev/null
+++ b/src/constant/travel-mode.js
@@ -0,0 +1,22 @@
+function travelModeList() {
+  return [
+    {
+      label: '椹捐溅',
+      value: 0
+    },
+    {
+      label: '鍏叡浜ら��',
+      value: 1
+    },
+    {
+      label: '姝ヨ',
+      value: 2
+    },
+  ];
+}
+
+function travelModeName(type) {
+  return travelModeList().find((v) => v.value == type).label;
+}
+
+export { travelModeList, travelModeName };
diff --git a/src/model/clueQuestion.js b/src/model/clueQuestion.js
index 87954a4..5616f09 100644
--- a/src/model/clueQuestion.js
+++ b/src/model/clueQuestion.js
@@ -1,8 +1,8 @@
-import { imgUrl } from '@/api/index';
+import { $clue } from '@/api/index';
 
 function getClueQuestion(data) {
   data.cqFilePath = data.cqFilePath.split(';').map((val) => {
-    return imgUrl + val;
+    return $clue.imgUrl + val;
   });
   return data;
 }
diff --git a/src/views/overlay-clue/ClueLayout.vue b/src/views/overlay-clue/ClueLayout.vue
index 4b786b6..c250f2d 100644
--- a/src/views/overlay-clue/ClueLayout.vue
+++ b/src/views/overlay-clue/ClueLayout.vue
@@ -8,6 +8,7 @@
         v-model:show="show"
         :clueData="selectedClue"
         @pushed="(e) => (selectedClue.cuploaded = e)"
+        @onClueTaskChange="handleClueTaskChange"
       ></ClueReport>
     </el-col>
   </el-row>
@@ -28,6 +29,10 @@
   show.value = true;
   selectedClue.value = clue;
 };
+
+function handleClueTaskChange() {
+  selectedClue.value.taskCount = 1;
+}
 </script>
 
 <style scoped></style>
diff --git a/src/views/overlay-clue/list/ClueManage.vue b/src/views/overlay-clue/list/ClueManage.vue
index 4999f83..b43cc8f 100644
--- a/src/views/overlay-clue/list/ClueManage.vue
+++ b/src/views/overlay-clue/list/ClueManage.vue
@@ -15,11 +15,6 @@
     </div>
     <el-scrollbar height="70vh" class="p-h-1">
       <ClueList :dataList="clueList" @itemSelected="selectClue">
-        <!-- <template #extra>
-          <el-button size="small" type="primary" @click="getClues">
-            鍙戝竷浠诲姟
-          </el-button>
-        </template> -->
       </ClueList>
     </el-scrollbar>
     <el-row justify="space-between" class="p-8">
@@ -42,7 +37,7 @@
 import clueApi from '@/api/clue/clueApi';
 import { onMapMounted } from '@/components/map/baseMap';
 import moment from 'moment';
-import { ref, onMounted } from 'vue';
+import { ref, onMounted, reactive } from 'vue';
 
 const emits = defineEmits('itemSelected');
 
diff --git a/src/views/overlay-clue/list/components/ClueList.vue b/src/views/overlay-clue/list/components/ClueList.vue
index b9158ce..0b1c0c2 100644
--- a/src/views/overlay-clue/list/components/ClueList.vue
+++ b/src/views/overlay-clue/list/components/ClueList.vue
@@ -10,7 +10,7 @@
       >
         <div class="clue-item">
           <el-row justify="space-between">
-            <el-col span="20">
+            <el-col :span="18">
               <div class="flex gap-1">
                 <div class="clue-num">{{ $nf(item.cid) }}</div>
                 <el-text class="fy-h1" truncated>{{
@@ -18,11 +18,16 @@
                 }}</el-text>
               </div>
             </el-col>
-            <!-- <el-col :span="4">
+            <el-col :span="6">
               <el-row justify="end">
-                <slot name="extra"></slot>
+                <el-tag
+                  :type="item.taskCount > 0 ? 'info' : 'danger'"
+                  effect="plain"
+                >
+                  {{ item.taskCount > 0 ? '宸插彂甯冧换鍔�' : '鏈彂甯冧换鍔�' }}
+                </el-tag>
               </el-row>
-            </el-col> -->
+            </el-col>
           </el-row>
           <el-space>
             <el-row align="middle">
diff --git a/src/views/overlay-clue/report/ClueReport.vue b/src/views/overlay-clue/report/ClueReport.vue
index dabd554..3f9ed43 100644
--- a/src/views/overlay-clue/report/ClueReport.vue
+++ b/src/views/overlay-clue/report/ClueReport.vue
@@ -56,20 +56,31 @@
       </el-scrollbar>
     </div>
   </CloseButton>
+  <ClueTaskEdit
+    v-model="clueTaskDialog"
+    :clue-task="clueTask"
+    :clue-data="clueData"
+    :create="isCreateMode"
+    @on-submit="handelClueTaskEdit"
+  ></ClueTaskEdit>
 </template>
 
 <script>
 import ClueReportClue from './components/ClueReportClue.vue';
 import ClueReportConclusion from './components/ClueReportConclusion.vue';
 import ClueReportQuestion from './components/ClueReportQuestion.vue';
+import ClueTaskEdit from '@/views/overlay-clue/task/ClueTaskEdit.vue';
+
 import { useMessageBoxTip } from '@/composables/messageBox';
 import clueApi from '@/api/clue/clueApi';
+import clueTaskApi from '@/api/clue/clueTaskApi';
 
 export default {
   components: {
     ClueReportClue,
     ClueReportConclusion,
-    ClueReportQuestion
+    ClueReportQuestion,
+    ClueTaskEdit
   },
   props: {
     clueData: {
@@ -80,11 +91,20 @@
     },
     show: Boolean
   },
-  emits: ['update:show', 'pushed'],
+  emits: ['update:show', 'pushed', 'onClueTaskChange'],
   data() {
     return {
-      clueTask: undefined
+      clueTask: undefined,
+      clueTaskDialog: false,
+      isCreateMode: true
     };
+  },
+  watch: {
+    clueData(nV, oV) {
+      if (nV && nV != oV) {
+        this.getClueTask();
+      }
+    }
   },
   methods: {
     closeEdit() {
@@ -104,8 +124,25 @@
         this.$emit('pushed', res);
       });
     },
-    publishTask() {
 
+    getClueTask() {
+      clueTaskApi
+        .fetchClueTask({ clueId: this.clueData.cid })
+        .then((res) => {
+          this.isCreateMode = res.data.length == 0;
+          if (res.data.length > 0) {
+            this.clueTask = res.data[0];
+          } else {
+            this.clueTask = undefined;
+          }
+        });
+    },
+    publishTask() {
+      this.clueTaskDialog = true;
+    },
+    handelClueTaskEdit() {
+      this.getClueTask();
+      this.$emit('onClueTaskChange');
     }
   }
 };
diff --git a/src/views/overlay-clue/task/ClueTaskEdit.vue b/src/views/overlay-clue/task/ClueTaskEdit.vue
index 61c7765..26aca1b 100644
--- a/src/views/overlay-clue/task/ClueTaskEdit.vue
+++ b/src/views/overlay-clue/task/ClueTaskEdit.vue
@@ -1,3 +1,288 @@
 <template>
-  
-</template>
\ No newline at end of file
+  <el-dialog
+    style="pointer-events: auto"
+    :model-value="modelValue"
+    @update:modelValue="handleDialogChange"
+    width="50%"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+    destroy-on-close
+  >
+    <template #header>
+      <span> {{ create ? '鍙戝竷绾跨储浠诲姟' : '鏇存柊绾跨储浠诲姟' }}</span>
+    </template>
+    <el-form
+      label-width="120px"
+      label-position="right"
+      :rules="rules"
+      :model="formObj"
+      ref="formRef"
+    >
+      <el-form-item label="绾跨储缂栧彿" prop="clueId">
+        <el-input
+          v-model="formObj.clueId"
+          placeholder="璇疯緭鍏ョ嚎绱㈢紪鍙�"
+          class="w-200"
+          :disabled="true"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="浠诲姟鏃堕棿" prop="taskTime">
+        <el-date-picker
+          v-model="formObj.taskTime"
+          type="date"
+          placeholder="閫夋嫨鏃ユ湡"
+        />
+      </el-form-item>
+      <el-form-item label="鍖哄幙" prop="_location">
+        <OptionLocation
+          :level="3"
+          :initValue="false"
+          :checkStrictly="false"
+          :allOption="false"
+          v-model="formObj._location"
+        ></OptionLocation>
+      </el-form-item>
+      <el-form-item label="鍝嶅簲绾у埆" prop="responseLevel">
+        <OptionResponseLevel
+          v-model="formObj.responseLevel"
+        ></OptionResponseLevel>
+      </el-form-item>
+      <el-form-item label="鍑鸿鏂瑰紡" prop="travelMode">
+        <OptionTravelMode
+          v-model="formObj.travelMode"
+        ></OptionTravelMode>
+      </el-form-item>
+      <el-form-item label="鏃犱汉鏈�" prop="hasUav">
+        <el-switch
+          v-model="formObj.hasUav"
+          inline-prompt
+          active-text="鏈�"
+          inactive-text="鏃�"
+        />
+      </el-form-item>
+      <el-form-item label="鎵ц浜�" prop="executorIds">
+        <OptionExecutors
+          v-model="formObj.executorIds"
+        ></OptionExecutors>
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button @click="onCancel">鍙栨秷</el-button>
+      <el-button
+        :disabled="!edit"
+        type="primary"
+        :loading="loading"
+        @click="onSubmit"
+        >纭畾</el-button
+      >
+    </template>
+  </el-dialog>
+</template>
+<script setup>
+import { ref, reactive, watch, onMounted } from 'vue';
+import { useFormConfirm } from '@/composables/formConfirm';
+import clueTaskApi from '@/api/clue/clueTaskApi';
+
+const props = defineProps({
+  modelValue: Boolean,
+  clueData: {
+    type: Object,
+    default: () => {
+      return {};
+    }
+  },
+  clueTask: Object,
+  create: {
+    type: Boolean,
+    default: true
+  }
+});
+
+const emits = defineEmits(['update:modelValue', 'onSubmit']);
+
+function handleDialogChange(value) {
+  emits('update:modelValue', value);
+}
+
+const { formObj, formRef, edit, onSubmit, onCancel, clear } =
+  useFormConfirm({
+    submit: {
+      do: submit
+    },
+    cancel: {
+      do: cancel
+    }
+  });
+const loading = ref(false);
+// 琛ㄥ崟妫�鏌ヨ鍒�
+const rules = reactive({
+  clueId: [
+    {
+      required: true,
+      message: '绾跨储缂栧彿涓嶈兘涓虹┖',
+      trigger: 'blur'
+    }
+  ],
+  taskTime: [
+    {
+      required: true,
+      message: '绾跨储鏃堕棿涓嶈兘涓虹┖',
+      trigger: 'change'
+    }
+  ],
+  _location: [
+    {
+      required: true,
+      message: '鍖哄幙涓嶈兘涓虹┖',
+      trigger: 'change'
+    }
+  ],
+  responseLevel: [
+    {
+      required: true,
+      message: '鍝嶅簲绾у埆涓嶈兘涓虹┖',
+      trigger: 'change'
+    }
+  ],
+  executorIds: [
+    {
+      required: true,
+      message: '鎵ц浜轰笉鑳戒负绌�',
+      trigger: 'change'
+    }
+  ]
+});
+
+function submit() {
+  const param = getParams();
+  return props.create ? createClueTask(param) : updateClueTask(param);
+}
+
+function cancel() {
+  emits('update:modelValue', false);
+}
+
+function createClueTask(param) {
+  return clueTaskApi
+    .createClueTask(param)
+    .then(() => {
+      emits('update:modelValue', false);
+      emits('onSubmit');
+      // clear();
+    })
+    .finally(() => {
+      loading.value = false;
+    });
+}
+
+function updateClueTask(param) {
+  return clueTaskApi
+    .updateClueTask(param)
+    .then(() => {
+      emits('update:modelValue', false);
+      emits('onSubmit');
+      // clear();
+    })
+    .finally(() => {
+      loading.value = false;
+    });
+}
+
+function getParams() {
+  return {
+    guid: formObj.value.guid,
+    clueId: formObj.value.clueId,
+    taskTime: formObj.value.taskTime,
+    provinceCode: formObj.value._location.pCode,
+    provinceName: formObj.value._location.pName,
+    cityCode: formObj.value._location.cCode,
+    cityName: formObj.value._location.cName,
+    districtCode: formObj.value._location.dCode,
+    districtName: formObj.value._location.dName,
+    townCode: formObj.value._location.tCode,
+    townName: formObj.value._location.tName,
+    responseLevel: formObj.value.responseLevel,
+    travelMode: formObj.value.travelMode,
+    hasUav: formObj.value.hasUav,
+    executorIds: formObj.value.executorIds.join(';')
+  };
+}
+
+// watch(
+//   () => props.clueData,
+//   (nV, oV) => {
+//     if (nV && nV != oV) {
+//       formObj.value.clueId = nV.cid;
+//     }
+//   }
+// );
+
+// watch(
+//   () => props.clueTask,
+//   (nV, oV) => {
+//     if (nV && nV != oV) {
+//       formObj.value.guid = nV.guid;
+//       formObj.value.clueId = nV.clueId;
+//       formObj.value.taskTime = nV.taskTime;
+//       formObj.value._location = {
+//         pCode: nV.provinceCode,
+//         pName: nV.provinceName,
+//         cCode: nV.cityCode,
+//         cName: nV.cityName,
+//         dCode: nV.districtCode,
+//         dName: nV.districtName,
+//         tCode: nV.townCode,
+//         tName: nV.townName
+//       };
+//       formObj.value.responseLevel = nV.responseLevel;
+//       formObj.value.travelMode = nV.travelMode;
+//       formObj.value.hasUav = nV.hasUav;
+//       formObj.value.executorIds = nV.executorIds.split(';');
+//     }
+//   }
+// );
+
+watch(
+  () => [props.modelValue, props.clueData, props.clueTask],
+  (nV, oV) => {
+    const [m, d, t] = nV;
+    if (m) {
+      formObj.value = {
+        taskTime: new Date(),
+        _location: {
+          pCode: '31',
+          pName: '涓婃捣甯�',
+          cCode: '3100',
+          cName: '涓婃捣甯�',
+          dCode: '310106',
+          dName: '闈欏畨鍖�',
+          tCode: undefined,
+          tName: undefined
+        }
+      };
+      if (d) {
+        formObj.value.clueId = d.cid;
+      }
+      if (t) {
+        formObj.value.guid = t.guid;
+        formObj.value.clueId = t.clueId;
+        formObj.value.taskTime = t.taskTime;
+        formObj.value._location = {
+          pCode: t.provinceCode,
+          pName: t.provinceName,
+          cCode: t.cityCode,
+          cName: t.cityName,
+          dCode: t.districtCode,
+          dName: t.districtName,
+          tCode: t.townCode,
+          tName: t.townName
+        };
+        formObj.value.responseLevel = t.responseLevel;
+        formObj.value.travelMode = t.travelMode;
+        formObj.value.hasUav = t.hasUav;
+        formObj.value.executorIds = t.executorIds.split(';');
+      }
+    }
+  }
+);
+</script>

--
Gitblit v1.9.3