Bläddra i källkod

Merge branch 'master' of http://59.110.6.97:3000/root/BoundLink-UI

liqh 3 månader sedan
förälder
incheckning
4293e0a8e6

+ 337 - 339
src/views/flow/stFormDesign/packages/UploadFile/uploadFile.vue

@@ -1,36 +1,32 @@
 <template>
   <div :style="{ width: record.options.width }">
     <a-upload-dragger
-        :class="{ 'hide-upload-drag': !(fileList.length < record.options.limit) }"
-        :disabled="record.options.disabled || parentDisabled"
-        :name="config.uploadFileName || record.options.fileName"
-        :data="config.uploadFileData || optionsData"
-        :headers="headers"
-        :action="getAction"
-        :multiple="record.options.multiple"
-        :fileList="fileList"
-        @preview="handlePreview"
-        @change="handleChange"
-        :beforeUpload="beforeUpload"
+      :class="{ 'hide-upload-drag': !(fileList.length < record.options.limit) }"
+      :disabled="record.options.disabled || parentDisabled"
+      :name="config.uploadFileName || record.options.fileName"
+      :data="config.uploadFileData || optionsData"
+      :headers="headers"
+      :action="getAction"
+      :multiple="record.options.multiple"
+      :fileList="fileList"
+      @preview="handlePreview"
+      @change="handleChange"
+      :beforeUpload="beforeUpload"
     >
       <p v-if="!record.options.disabled" class="ant-upload-text">单击或拖动文件到此区域</p>
       <template #itemRender="{ file, actions }">
         <div style="display: flex; justify-content: space-between; align-items: center">
           <a :style="file.status === 'error' ? 'color: red' : ''" @click="handlePreview(file)">{{ file.name }}</a>
           <a-space style="margin-right: 10px">
-            <span style="color:#1677ff" v-show="file.originFileObj=='[object File]'">
-            上传进度:{{ file.percent.toFixed(2) }}%
-            </span>
-            <a style="font-size:16px;margin-right: 10px" href="javascript:;" @click="handlePreview(file)">
-              <EyeOutlined/>
+            <span style="color: #1677ff" v-show="file.originFileObj == '[object File]'"> 上传进度:{{ file.percent.toFixed(2) }}% </span>
+            <a style="font-size: 16px; margin-right: 10px" href="javascript:;" @click="handlePreview(file)">
+              <EyeOutlined />
             </a>
-            <a style="font-size:16px;margin-right: 10px" v-if="!this.$route.query.isMobile"
-               @click="handleDownload(file)">
-              <DownloadOutlined/>
+            <a style="font-size: 16px; margin-right: 10px" v-if="!this.$route.query.isMobile" @click="handleDownload(file)">
+              <DownloadOutlined />
             </a>
-            <a style="font-size:16px;color: red" href="javascript:;" v-if="!record.options.disabled"
-               @click="handleRemove(file)">
-              <DeleteOutlined/>
+            <a style="font-size: 16px; color: red" href="javascript:;" v-if="!record.options.disabled" @click="handleRemove(file)">
+              <DeleteOutlined />
             </a>
           </a-space>
         </div>
@@ -38,19 +34,19 @@
     </a-upload-dragger>
     <!-- 预览弹框 -->
     <vue-draggable-resizable
-        v-show="previewVisible"
-        :x="x1"
-        :y="y1"
-        :w="width"
-        :h="height"
-        class="popup-resize"
-        :resizable="true"
-        :draggable="draggableResize"
-        @resizing="handleResizing"
-        @dragging="onDragging"
-        :active="previewActive"
-        :min-width="300"
-        :min-height="100"
+      v-show="previewVisible"
+      :x="x1"
+      :y="y1"
+      :w="width"
+      :h="height"
+      class="popup-resize"
+      :resizable="true"
+      :draggable="draggableResize"
+      @resizing="handleResizing"
+      @dragging="onDragging"
+      :active="previewActive"
+      :min-width="300"
+      :min-height="100"
     >
       <div class="draggable-title">
         <span class="preview-left">附件预览</span>
@@ -65,30 +61,33 @@
       </div>
       <div class="control-buttons">
         <a-button v-show="!maxed" class="control-button" @click="maximize">
-          <ExpandOutlined/> <!-- 最大化图标 -->
+          <ExpandOutlined />
+          <!-- 最大化图标 -->
         </a-button>
         <a-button v-show="maxed" class="control-button" @click="restore">
-          <ShrinkOutlined/> <!-- 返回图标 -->
+          <ShrinkOutlined />
+          <!-- 返回图标 -->
         </a-button>
         <a-button class="control-button" @click="closeDrag">
-          <CloseOutlined/> <!-- 关闭图标 -->
+          <CloseOutlined />
+          <!-- 关闭图标 -->
         </a-button>
       </div>
     </vue-draggable-resizable>
 
     <a-drawer
-        title="附件预览"
-        placement="bottom"
-        :visible="previewVisibleMobile"
-        @close="previewVisibleMobile = false"
-        height="90%"
-        width="100vw"
-        :closable="true"
-        :bodyStyle="{
+      title="附件预览"
+      placement="bottom"
+      :visible="previewVisibleMobile"
+      @close="previewVisibleMobile = false"
+      height="90%"
+      width="100vw"
+      :closable="true"
+      :bodyStyle="{
         padding: '0',
         scrollbarWidth: 'none' /* Firefox */,
       }"
-        :drawerStyle="{
+      :drawerStyle="{
         scrollbarWidth: 'none' /* Firefox */,
       }"
     >
@@ -97,327 +96,326 @@
   </div>
 </template>
 <script>
-import {fileApi} from '/@/api/support/file-api';
-import {localRead} from '/@/utils/local-util';
-import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js';
-import {useUserStore} from '/@/store/modules/system/user.js';
-import dayjs from 'dayjs';
-import {Base64} from 'js-base64';
-import {message, Modal} from 'ant-design-vue';
-import VueDraggableResizable from 'vue-draggable-resizable'
-import "vue-draggable-resizable/style.css";
+  import { fileApi } from '/@/api/support/file-api';
+  import { localRead } from '/@/utils/local-util';
+  import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js';
+  import { useUserStore } from '/@/store/modules/system/user.js';
+  import dayjs from 'dayjs';
+  import { Base64 } from 'js-base64';
+  import { message, Modal } from 'ant-design-vue';
+  import VueDraggableResizable from 'vue-draggable-resizable';
+  import 'vue-draggable-resizable/style.css';
 
-const fileUrl = import.meta.env.VITE_APP_API_FILE_VIEW_URL;
-export default {
-  name: 'StUploadFile',
-  props: ['record', 'value', 'config', 'parentDisabled', 'dynamicData'],
-  components: {
-    VueDraggableResizable
-  },
-  data() {
-    return {
-      fileList: [],
-      getAction: import.meta.env.VITE_APP_API_URL + '/support/file/upload?folder=1',
-      headers: {'x-access-token': localRead(LocalStorageKeyConst.USER_TOKEN)},
-      previewVisible: false, // 控制弹框显示
-      previewVisibleMobile: false,
-      previewUrl: '', // 预览的 URL
-      x1: 100,
-      y1: 10,
-      x2: 100,
-      y2: 10,
-      width: 0,
-      height: 0,
-      lastWidth: 0,
-      lastHeight: 0,
-      maxed: false,
-      scaleFactor: 1.1,
-      iframeShow: true,
-      previewActive: false,
-      fileName: '',
-      draggableResize: true,
-    };
-  },
-  mounted() {
-    this.width = window.innerWidth - 200
-    this.height = window.innerHeight - 90
-    document.addEventListener('mouseup', this.handleGlobalMouseUp);
-  },
-  beforeDestroy() {
-    // 在组件销毁时移除全局 mouseup 事件
-    document.removeEventListener('mouseup', this.handleGlobalMouseUp);
-  },
-  watch: {
-    value: {
-      // value 需要深度监听及默认先执行handler函数
-      handler(val) {
-        if (val) {
-          this.setFileList();
-        }
-      },
-      immediate: true,
-      deep: true,
-    },
-  },
-  computed: {
-    optionsData() {
-      try {
-        return this.record.options.data && JSON.parse(this.record.options.data);
-      } catch (err) {
-        console.error(err);
-        return {};
-      }
+  const fileUrl = import.meta.env.VITE_APP_API_FILE_VIEW_URL;
+  export default {
+    name: 'StUploadFile',
+    props: ['record', 'value', 'config', 'parentDisabled', 'dynamicData'],
+    components: {
+      VueDraggableResizable,
     },
-  },
-  methods: {
-    setFileList() {
-      // 当传入value改变时,fileList也要改变
-      // 如果传入的值为字符串,则转成json
-      if (typeof this.value === 'string') {
-        if (this.value.indexOf('fakepath') < 0) {
-          this.fileList = JSON.parse(this.value);
-          // 将转好的json覆盖组件默认值的字符串
-          this.handleSelectChange();
-        }
-      } else {
-        this.fileList = this.value;
-      }
-    },
-    // 调整大小过程中持续触发
-    handleResizing(x, y, width, height) {
-      this.x1 = x
-      this.y1 = y
-      this.width = width
-      this.height = height
-      this.iframeShow = false
-      this.maxed = false
+    data() {
+      return {
+        fileList: [],
+        getAction: import.meta.env.VITE_APP_API_URL + '/support/file/upload?folder=1',
+        headers: { 'x-access-token': localRead(LocalStorageKeyConst.USER_TOKEN) },
+        previewVisible: false, // 控制弹框显示
+        previewVisibleMobile: false,
+        previewUrl: '', // 预览的 URL
+        x1: 100,
+        y1: 10,
+        x2: 100,
+        y2: 10,
+        width: 0,
+        height: 0,
+        lastWidth: 0,
+        lastHeight: 0,
+        maxed: false,
+        scaleFactor: 1.1,
+        iframeShow: true,
+        previewActive: false,
+        fileName: '',
+        draggableResize: true,
+      };
     },
-    onDragging(x, y) {
-      this.x1 = x
-      this.y1 = y
-      this.maxed = false
+    mounted() {
+      this.width = window.innerWidth - 200;
+      this.height = window.innerHeight - 90;
+      document.addEventListener('mouseup', this.handleGlobalMouseUp);
     },
-    handleGlobalMouseUp() {
-      this.iframeShow = true
+    beforeDestroy() {
+      // 在组件销毁时移除全局 mouseup 事件
+      document.removeEventListener('mouseup', this.handleGlobalMouseUp);
     },
-    handleSelectChange() {
-      setTimeout(() => {
-        this.$emit('update:value', this.fileList); //主表,直接更新value
-        this.$emit('change', this.fileList); //如果是子表,则通过change更新
-        this.$emit('input', this.fileList);
-      }, 10);
+    watch: {
+      value: {
+        // value 需要深度监听及默认先执行handler函数
+        handler(val) {
+          if (val) {
+            this.setFileList();
+          }
+        },
+        immediate: true,
+        deep: true,
+      },
     },
-    handleDownload(file) {
-      fileApi.downLoadFile(file.response.data.fileKey);
+    computed: {
+      optionsData() {
+        try {
+          return this.record.options.data && JSON.parse(this.record.options.data);
+        } catch (err) {
+          console.error(err);
+          return {};
+        }
+      },
     },
-    handlePreview(file) {
-      // 预览
-      const url = file.response.data.fileUrl || file.url || file.thumbUrl;
-      const userStore = useUserStore();
-      const waterMark = [
-        userStore.actualName + '-' + (userStore.phone == undefined ? '0000' : userStore.phone?.slice(-4)),
-        dayjs().format('YYYY-MM-DD HH:mm:ss'),
-      ];
-      const viewFile = fileUrl + '/onlinePreview?url=' + encodeURIComponent(Base64.encode(url)) + '&watermarkTxt=' + waterMark;
-      if (this.$route.query.isMobile === 'true') {
-        // window.open(viewFile);
-        this.previewVisible = false; // 显示弹框
+    methods: {
+      setFileList() {
+        // 当传入value改变时,fileList也要改变
+        // 如果传入的值为字符串,则转成json
+        if (typeof this.value === 'string') {
+          if (this.value.indexOf('fakepath') < 0) {
+            this.fileList = JSON.parse(this.value);
+            // 将转好的json覆盖组件默认值的字符串
+            this.handleSelectChange();
+          }
+        } else {
+          this.fileList = this.value;
+        }
+      },
+      // 调整大小过程中持续触发
+      handleResizing(x, y, width, height) {
+        this.x1 = x;
+        this.y1 = y;
+        this.width = width;
+        this.height = height;
+        this.iframeShow = false;
+        this.maxed = false;
+      },
+      onDragging(x, y) {
+        this.x1 = x;
+        this.y1 = y;
+        this.maxed = false;
+      },
+      handleGlobalMouseUp() {
+        this.iframeShow = true;
+      },
+      handleSelectChange() {
+        setTimeout(() => {
+          this.$emit('update:value', this.fileList); //主表,直接更新value
+          this.$emit('change', this.fileList); //如果是子表,则通过change更新
+          this.$emit('input', this.fileList);
+        }, 10);
+      },
+      handleDownload(file) {
+        fileApi.downLoadFile(file.response.data.fileKey);
+      },
+      handlePreview(file) {
+        // 预览
+        const url = file.response.data.fileUrl || file.url || file.thumbUrl;
+        const userStore = useUserStore();
+        const waterMark = [
+          userStore.actualName + '-' + (userStore.phone == undefined ? '0000' : userStore.phone?.slice(-4)),
+          dayjs().format('YYYY-MM-DD HH:mm:ss'),
+        ];
+        const viewFile = fileUrl + '/onlinePreview?url=' + encodeURIComponent(Base64.encode(url)) + '&watermarkTxt=' + waterMark;
+        if (this.$route.query.isMobile === 'true') {
+          // window.open(viewFile);
+          this.previewVisible = false; // 显示弹框
 
-        this.previewUrl = viewFile;
-        this.previewVisibleMobile = true;
-      } else {
-        this.previewUrl = viewFile;
-        this.fileName = file.name
-        this.previewVisible = true; // 显示弹框
-        this.previewActive = true;
-      }
-    },
-    handleRemove(file) {
-      this.fileList = this.fileList.filter((item) => item.uid !== file.uid);
-      this.handleSelectChange();
-    },
-    beforeUpload(e, files) {
-      // if (files.length + this.fileList.length > this.record.options.limit) {
-      //   this.$message.warning(`最大上传数量为${this.record.options.limit}`)
-      //   files.splice(this.record.options.limit - this.fileList.length)
-      // }
-    },
-    handleChange(info) {
-      this.fileList = info.fileList;
-      if (info.file.status === 'done') {
-        const res = info.file.response;
-        if (res.code === 0) {
-          this.handleSelectChange();
+          this.previewUrl = viewFile;
+          this.previewVisibleMobile = true;
         } else {
-          this.fileList.pop();
+          this.previewUrl = viewFile;
+          this.fileName = file.name;
+          this.previewVisible = true; // 显示弹框
+          this.previewActive = true;
+        }
+      },
+      handleRemove(file) {
+        this.fileList = this.fileList.filter((item) => item.uid !== file.uid);
+        this.handleSelectChange();
+      },
+      beforeUpload(e, files) {
+        // if (files.length + this.fileList.length > this.record.options.limit) {
+        //   this.$message.warning(`最大上传数量为${this.record.options.limit}`)
+        //   files.splice(this.record.options.limit - this.fileList.length)
+        // }
+      },
+      handleChange(info) {
+        this.fileList = info.fileList;
+        if (info.file.status === 'done') {
+          const res = info.file.response;
+          if (res.code === 0) {
+            this.handleSelectChange();
+          } else {
+            this.fileList.pop();
+            this.$message.error(`文件上传失败`);
+          }
+        } else if (info.file.status === 'error') {
           this.$message.error(`文件上传失败`);
         }
-      } else if (info.file.status === 'error') {
-        this.$message.error(`文件上传失败`);
-      }
-    },
-    closeDrag() {
-      this.previewVisible = false
-    },
-    maximize() {
-      this.maxed = true
-      this.lastWidth = this.width
-      this.lastHeight = this.height
-      this.x2 = this.x1
-      this.y2 = this.y1
-      this.width = window.innerWidth
-      this.height = window.innerHeight
-      this.x1 = 0
-      this.y1 = 0
-      this.draggableResize=false
+      },
+      closeDrag() {
+        this.previewVisible = false;
+      },
+      maximize() {
+        this.maxed = true;
+        this.lastWidth = this.width;
+        this.lastHeight = this.height;
+        this.x2 = this.x1;
+        this.y2 = this.y1;
+        this.width = window.innerWidth;
+        this.height = window.innerHeight;
+        this.x1 = 0;
+        this.y1 = 0;
+        this.draggableResize = false;
+      },
+      restore() {
+        this.width = this.lastWidth;
+        this.height = this.lastHeight;
+        this.x1 = this.x2;
+        this.y1 = this.y2;
+        this.maxed = false;
+        this.draggableResize = true;
+      },
     },
-    restore() {
-      this.width = this.lastWidth
-      this.height = this.lastHeight
-      this.x1 = this.x2
-      this.y1 = this.y2
-      this.maxed = false
-      this.draggableResize=true
-    }
-  },
-};
+  };
 </script>
 <style scoped lang="scss">
-.fullscreen-modal {
-  width: 100vw !important;
-  height: 100vh !important;
-  max-width: 100vw !important;
-  margin: 0 !important;
-  padding: 0 !important;
-}
+  .fullscreen-modal {
+    width: 100vw !important;
+    height: 100vh !important;
+    max-width: 100vw !important;
+    margin: 0 !important;
+    padding: 0 !important;
+  }
 
-.fullscreen-modal .ant-modal-content {
-  height: 100vh !important;
-  display: flex;
-  flex-direction: column;
-}
+  .fullscreen-modal .ant-modal-content {
+    height: 100vh !important;
+    display: flex;
+    flex-direction: column;
+  }
 
-.fullscreen-modal .ant-modal-body {
-  flex: 1;
-}
+  .fullscreen-modal .ant-modal-body {
+    flex: 1;
+  }
 
-:deep(.ant-upload-wrapper) .ant-upload-drag .ant-upload {
-  padding: 0px 0px 0px 0;
-  background-color: #dde5f6;
-}
+  :deep(.ant-upload-wrapper) .ant-upload-drag .ant-upload {
+    padding: 0px 0px 0px 0;
+    background-color: #dde5f6;
+  }
 
-:deep(.vdr) {
-  z-index: 10000 !important;
-  position: fixed;
-  left: 0;
-  top: 0;
-}
+  :deep(.vdr) {
+    z-index: 10000 !important;
+    position: fixed;
+    left: 0;
+    top: 0;
+  }
 
-.drag_btn {
-  background: #fff;
-  display: flex;
-  justify-content: center;
+  .drag_btn {
+    background: #fff;
+    display: flex;
+    justify-content: center;
 
-  button {
-    font-size: 20px;
-    width: 70px;
+    button {
+      font-size: 20px;
+      width: 70px;
+    }
   }
-}
 
-.control-buttons {
-  background-color: #ffffff;
-  display: flex;
-  align-items: center;
-  justify-content: flex-end;
-  position: absolute;
-  right: 8px;
-  top: 2px;
-  z-index: 100;
-}
-
-.control-button {
-  font-size: 16px;
-  margin-left: 8px; /* 按钮之间的间距 */
-  background: none;
-  border: none;
-  cursor: pointer;
-}
+  .control-buttons {
+    background-color: #ffffff;
+    display: flex;
+    align-items: center;
+    justify-content: flex-end;
+    position: absolute;
+    right: 8px;
+    top: 2px;
+    z-index: 100;
+  }
 
-.draggable-title {
-  display: flex;
-  justify-content: space-between; /* 子元素之间的间距均匀分布 */
-  align-items: center; /* 垂直居中 */
-  padding: 8px;
-  cursor: move;
-  background-color: #ffffff;
-  position: absolute;
-  top: 0;
-  left: 0;
-  right: 0;
-  z-index: 10;
-}
+  .control-button {
+    font-size: 16px;
+    margin-left: 8px; /* 按钮之间的间距 */
+    background: none;
+    border: none;
+    cursor: pointer;
+  }
 
-.preview-left {
-  margin-left: 20px;
-  color: rgba(0, 0, 0, 0.88);
-  font-weight: 600;
-  font-size: 16px;
-  line-height: 1.5;
-}
+  .draggable-title {
+    display: flex;
+    justify-content: space-between; /* 子元素之间的间距均匀分布 */
+    align-items: center; /* 垂直居中 */
+    padding: 8px;
+    cursor: move;
+    background-color: #ffffff;
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    z-index: 10;
+  }
 
-.preview-title {
-  margin: 0 auto;
-  color: rgba(0, 0, 0, 0.88);
-  font-weight: 600;
-  font-size: 16px;
-  line-height: 1.5;
-}
+  .preview-left {
+    margin-left: 20px;
+    color: rgba(0, 0, 0, 0.88);
+    font-weight: 600;
+    font-size: 16px;
+    line-height: 1.5;
+  }
 
-.draggable-content {
-  width: 100%;
-  height: 100%;
-  padding: 36px 22px 22px 22px;
-  cursor: move;
-}
+  .preview-title {
+    margin: 0 auto;
+    color: rgba(0, 0, 0, 0.88);
+    font-weight: 600;
+    font-size: 16px;
+    line-height: 1.5;
+  }
 
-.popup-resize {
-  background-color: #ffffff;
-  border: 1px dashed #ffffff; /* 虚线边框,蓝色 */
-  border-radius: 8px; /* 圆角边框 */
-  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 添加阴影 */
-}
+  .draggable-content {
+    width: 100%;
+    height: 100%;
+    padding: 36px 22px 22px 22px;
+    cursor: move;
+  }
 
-.overlay {
-  position: absolute;
-  top: 60px;
-  left: 0;
-  width: 100%;
-  height: 100%;
-  pointer-events: none; /* 防止鼠标事件干扰 iframe */
-}
+  .popup-resize {
+    background-color: #ffffff;
+    border: 1px dashed #ffffff; /* 虚线边框,蓝色 */
+    border-radius: 8px; /* 圆角边框 */
+    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 添加阴影 */
+  }
 
-.horizontal {
-  height: 1px;
-  width: 100%;
-  border-color: #7cb305;
-  font-size: 18px;
-  font-weight: 600;
-  borderWidth: 2px;
-  color: #0D366F;
-}
+  .overlay {
+    position: absolute;
+    top: 60px;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    pointer-events: none; /* 防止鼠标事件干扰 iframe */
+  }
 
-.vertical {
-  display: inline-flex !important;
-  align-items: center !important;
-  font-size: 18px;
-  font-weight: 600;
-  borderWidth: 2px;
-  color: #0D366F;
-  height: 100%;
-  border-color: #7cb305;
-  top: -92px;
-  z-index: 12;
-  margin-left: 70px;
-}
+  .horizontal {
+    height: 1px;
+    width: 100%;
+    border-color: #7cb305;
+    font-size: 18px;
+    font-weight: 600;
+    border-width: 2px;
+    color: #0d366f;
+  }
 
+  .vertical {
+    display: inline-flex !important;
+    align-items: center !important;
+    font-size: 18px;
+    font-weight: 600;
+    border-width: 2px;
+    color: #0d366f;
+    height: 100%;
+    border-color: #7cb305;
+    top: -92px;
+    z-index: 12;
+    margin-left: 70px;
+  }
 </style>

+ 76 - 111
src/views/project/project-manage/project-create/index.vue

@@ -9,12 +9,13 @@
               <span class="basic-title-text">项目信息</span>
             </div>
             <div class="basic-title-right">
+              <a-button type="primary" @click="reset">重置</a-button>
               <a-button type="primary" @click="submit">提交</a-button>
             </div>
           </div>
           <div class="steps-content">
             <a-row :gutter="16" class="smart-query-form-row">
-              <a-col :span="8">
+              <a-col :span="16">
                 <a-form-item label="项目名称" name="deliveryName" class="smart-query-form-item">
                   <a-input v-model:value="formModel.deliveryName" placeholder="请输入项目名称" />
                 </a-form-item>
@@ -24,91 +25,66 @@
                   <DictSelect key-code="MATE_DELIVERY_TYPE" v-model:value="formModel.deliveryType" placeholder="请选择项目类型" width="100%" />
                 </a-form-item>
               </a-col>
-              <a-col :span="8">
-                <a-form-item label="项目类别" name="deliveryType" class="smart-query-form-item">
-                  <DictSelect key-code="MATE_DELIVERY_TYPE" v-model:value="formModel.deliveryType" placeholder="请选择项目类型" width="100%" />
-                </a-form-item>
-              </a-col>
             </a-row>
             <a-row :gutter="16" class="smart-query-form-row">
               <a-col :span="8">
-                <a-form-item label="项目状态" name="customerType" class="smart-query-form-item">
-                  <DictSelect key-code="MATE_CUSTOMER_TYPE" v-model:value="formModel.customerType" placeholder="请选择项目状态" width="100%" />
-                </a-form-item>
-              </a-col>
-              <a-col :span="8">
-                <a-form-item label="客户名称" name="customerName" class="smart-query-form-item">
-                  <a-input v-model:value="formModel.customerName" placeholder="请输入客户名称" />
-                </a-form-item>
-              </a-col>
-              <a-col :span="8">
-                <a-form-item label="服务客户" name="deliveryType" class="smart-query-form-item">
-                  <DictSelect key-code="MATE_DELIVERY_TYPE" v-model:value="formModel.deliveryType" placeholder="请选择项目类型" width="100%" />
+                <a-form-item label="项目状态" name="deliveryStatus" class="smart-query-form-item">
+                  <DictSelect key-code="MATE_DELIVERY_STATUS" v-model:value="formModel.deliveryStatus" placeholder="请选择项目状态" width="100%" />
                 </a-form-item>
               </a-col>
-            </a-row>
-            <a-row :gutter="16" class="smart-query-form-row">
               <a-col :span="8">
-                <a-form-item label="客户经理" name="deliveryCharge1" class="smart-query-form-item">
+                <a-form-item label="交付经理" name="deliveryCharge1" class="smart-query-form-item">
                   <a-input
                     v-model:value="formModel.deliveryCharge1"
                     placeholder="请选择岗位人员"
-                    @click="showSelectUser('deliveryManager')"
-                    allowClear
+                    @click="showSelectUser('deliveryManager', index)"
+                    readonly
+                  />
+                  <EmployeeTableSelectModal
+                    ref="selectDeliveryManagerRef"
+                    type="radio"
+                    @selectDataList="selectedUser('deliveryManager', index, $event)"
                   />
-                  <EmployeeTableSelectModal ref="selectDeliveryManagerRef" type="radio" @selectDataList="selectedUser('deliveryManager', $event)" />
                 </a-form-item>
               </a-col>
               <a-col :span="8">
-                <a-form-item label="项目经理" name="marketManagerCode" class="smart-query-form-item">
+                <a-form-item label="营销经理" name="marketManagerCode" class="smart-query-form-item">
                   <a-input
                     v-model:value="formModel.marketManagerCode"
                     placeholder="请选择岗位人员"
-                    @click="showSelectUser('marketManager')"
-                    allowClear
+                    @click="showSelectMarketManager('marketManager', index)"
+                    readonly
                   />
-                  <EmployeeTableSelectModal ref="selectMarketManagerRef" type="radio" @selectDataList="selectedUser('marketManager', $event)" />
-                </a-form-item>
-              </a-col>
-              <a-col :span="8">
-                <a-form-item label="产品经理" name="productManagerCode" class="smart-query-form-item">
-                  <a-input
-                    v-model:value="formModel.productManagerCode"
-                    placeholder="请选择岗位人员"
-                    @click="showSelectUser('productManager')"
-                    allowClear
+                  <EmployeeTableSelectModal
+                    ref="selectMarketManagerRef"
+                    type="radio"
+                    @selectDataList="selectedMarketManager('marketManager', index, $event)"
                   />
-                  <EmployeeTableSelectModal ref="selectProductManagerRef" @selectDataList="selectedUser('productManager', $event)" />
                 </a-form-item>
               </a-col>
             </a-row>
+          </div>
+        </div>
+        <div>
+          <div class="basic-title">
+            <div class="basic-title-left">
+              <div class="basic-title-line"></div>
+              <span class="basic-title-text">客户信息</span>
+            </div>
+            <div class="basic-title-right">
+              <!-- <a-button type="primary">提交</a-button> -->
+            </div>
+          </div>
+          <div class="steps-content">
             <a-row :gutter="16" class="smart-query-form-row">
               <a-col :span="8">
-                <a-form-item label="前端开发" name="frontendDeveloper" class="smart-query-form-item">
-                  <a-input
-                    v-model:value="formModel.frontendDeveloper"
-                    placeholder="请选择岗位人员"
-                    @click="showSelectUser('frontendDeveloper')"
-                    allowClear
-                  />
-                  <EmployeeTableSelectModal ref="selectFrontendDeveloperRef" @selectDataList="selectedUser('frontendDeveloper', $event)" />
-                </a-form-item>
-              </a-col>
-              <a-col :span="8">
-                <a-form-item label="后端开发" name="backendDeveloper" class="smart-query-form-item">
-                  <a-input
-                    v-model:value="formModel.backendDeveloper"
-                    placeholder="请选择岗位人员"
-                    @click="showSelectUser('backendDeveloper')"
-                    allowClear
-                  />
-                  <EmployeeTableSelectModal ref="selectBackendDeveloperRef" @selectDataList="selectedUser('backendDeveloper', $event)" />
+                <a-form-item label="客户名称" name="customerName" class="smart-query-form-item">
+                  <a-input v-model:value="formModel.customerName" placeholder="请输入客户名称" />
                 </a-form-item>
               </a-col>
               <a-col :span="8">
-                <a-form-item label="测试" name="tester" class="smart-query-form-item">
-                  <a-input v-model:value="formModel.tester" placeholder="请选择岗位人员" @click="showSelectUser('tester')" allowClear />
-                  <EmployeeTableSelectModal ref="selectTesterRef" @selectDataList="selectedUser('tester', $event)" />
+                <a-form-item label="客户类型" name="customerType" class="smart-query-form-item">
+                  <DictSelect key-code="MATE_CUSTOMER_TYPE" v-model:value="formModel.customerType" placeholder="请选择项目状态" width="100%" />
                 </a-form-item>
               </a-col>
             </a-row>
@@ -153,7 +129,6 @@
     </a-form>
   </a-card>
 </template>
-
 <script setup>
   import { onMounted, reactive, ref, useAttrs } from 'vue';
   import { useRouter } from 'vue-router';
@@ -168,44 +143,35 @@
   const stepFormRef = ref(null);
   const router = useRouter();
 
-  // 数据
+  // --------------------- 数据 ---------------------
   const formModel = reactive({
-    deliveryName: undefined, // 项目名称
-    deliveryType: undefined, // 项目类型
-    deliveryStatus: undefined, // 项目状态
-    deliveryCharge: undefined, // 项目负责人
-    deliveryCharge1: undefined, // 客户经理显示的字符串
-    deliveryCharge1List: [], // 客户经理选中的用户列表
-    marketManager: undefined, // 营销经理
+    deliveryName: undefined, //项目名称
+    deliveryType: undefined, //项目类型
+    deliveryStatus: undefined, //项目状态
+    deliveryCharge: undefined, //项目负责人
+    deliveryCharge1: undefined,
+    marketManager: undefined, //营销经理
     marketManagerCode: undefined,
-    productManager: undefined, // 产品经理
-    productManagerCode: undefined,
-    customerName: undefined, // 客户名称
-    customerType: undefined, // 客户类型
-    remark: undefined, // 备注信息
-    attachment: undefined, // 附件集合
-    frontendDeveloper: undefined, // 前端开发
-    frontendDeveloperList: [],
-    backendDeveloper: undefined, // 后端开发
-    backendDeveloperList: [],
-    tester: undefined, // 测试
-    testerList: [],
+    customerName: undefined, //客户名称
+    customerType: undefined, //客户类型
+    remark: undefined, //	备注信息
+    attachment: undefined, //附件集合
   });
 
-  // 校验规则
+  // --------------------- 校验规则 ---------------------
   const formRules = {
     deliveryName: [{ required: true, message: '请输入项目名称', trigger: 'change' }],
     deliveryType: [{ required: true, message: '请选择项目类型', trigger: 'change' }],
     deliveryStatus: [{ required: true, message: '请选择项目状态', trigger: 'change' }],
-    deliveryCharge: [{ required: true, message: '请选择交付经理', trigger: 'change' }],
-    marketManager: [{ required: true, message: '请选择营销经理', trigger: 'change' }],
+    deliveryCharge1: [{ required: true, message: '请选择交付经理', trigger: 'change' }],
+    marketManagerCode: [{ required: true, message: '请选择营销经理', trigger: 'change' }],
     customerName: [{ required: true, message: '请输入客户名称', trigger: 'change' }],
     customerType: [{ required: true, message: '请选择客户类型', trigger: 'change' }],
   };
 
   const labelCol = { style: { width: '128px' } };
 
-  // 步骤相关
+  // ----------------------- 步骤相关 ---------------------------
   const query = router.currentRoute.value.query;
   console.log('query', query);
 
@@ -247,7 +213,8 @@
     }
   }
 
-  // 提交
+  //-----------------------------提交\重置---------------------------------
+
   const submit = () => {
     console.log('formModel', formModel);
     stepFormRef.value
@@ -276,45 +243,42 @@
     });
   };
 
-  // 重置
   const reset = () => {
     Object.keys(formModel).forEach((key) => {
       formModel[key] = undefined;
     });
   };
 
-  // 人员选择
+  //---------------------------人员选择------------------------------
+
   const selectDeliveryManagerRef = ref(null);
   const selectMarketManagerRef = ref(null);
-  const selectProductManagerRef = ref(null);
-  const selectFrontendDeveloperRef = ref(null);
-  const selectBackendDeveloperRef = ref(null);
-  const selectTesterRef = ref(null);
+  function showSelectMarketManager(type) {
+    if (type === 'marketManager') {
+      selectMarketManagerRef.value.showModal();
+    }
+  }
 
   function showSelectUser(type) {
-    const refs = {
-      deliveryManager: selectDeliveryManagerRef,
-      marketManager: selectMarketManagerRef,
-      productManager: selectProductManagerRef,
-      frontendDeveloper: selectFrontendDeveloperRef,
-      backendDeveloper: selectBackendDeveloperRef,
-      tester: selectTesterRef,
-    };
-    refs[type].value.showModal();
+    if (type === 'deliveryManager') {
+      selectDeliveryManagerRef.value.showModal();
+    }
+  }
+  function selectedUser(field, index, list) {
+    if (field === 'deliveryManager') {
+      formModel.deliveryCharge1 = list[0].actualName;
+      formModel.deliveryCharge = list[0].loginName;
+    }
   }
 
-  function selectedUser(type, list) {
-    console.info('Selected users for', type, list);
-    const field = `${type}List`;
-    const displayField = type === 'deliveryManager' ? 'deliveryCharge1' : type;
-    formModel[field] = list.map((item) => ({
-      actualName: item.actualName,
-      loginName: item.loginName,
-    }));
-    formModel[displayField] = list.map((item) => item.actualName).join(', ');
+  function selectedMarketManager(field, index, list) {
+    console.info(1111111111111111111111);
+    formModel.marketManagerCode = list[0].actualName;
+    formModel.marketManager = list[0].loginName;
   }
 
-  // 上传附件
+  // ----------------------- 上传附件 ----------------------------
+  // 已上传的附件列表
   const defaultFileList = ref([]);
   function changeAttachment(fileList) {
     defaultFileList.value = fileList;
@@ -327,6 +291,7 @@
     display: flex;
     flex-direction: column;
     gap: 20px;
+    // width: 1350px;
     margin: 0 auto;
 
     .basic-title {

+ 5 - 1
src/views/project/report-manage/report-today/index.vue

@@ -20,7 +20,7 @@
                 <a-switch v-model:checked="formModel.siteState" />
               </a-form-item>
             </a-col>
-            <a-col :span="12">
+            <a-col :span="12" v-if="formModel.siteState">
               <a-form-item label="驻场客户" name="customerName" class="smart-query-form-item">
                 <a-input allowClear v-model:value="formModel.customerName" placeholder="请选择驻场客户" @click="showSelectCustomer" />
               </a-form-item>
@@ -149,6 +149,10 @@
   const reportTodayDetailRef = ref();
   const reportHistroyDetailRef = ref();
 
+  const formRules = {
+    customerName: [{ required: true, message: '请选择驻场客户', trigger: 'change' }],
+  };
+
   //表单字段定义
   const formModel = reactive({
     customerId: undefined,

+ 56 - 41
src/views/project/task-manage/task-create/index.vue

@@ -36,11 +36,11 @@
                 </a-form-item>
               </a-col>
               <a-col :span="8">
-                <a-form-item label="任务标签" name="rushState" class="smart-query-form-item">
+                <a-form-item label="任务标签" name="taskLabel" class="smart-query-form-item">
                   <DictSelect
                     key-code="BLINK_DELIVERY_SPECIAL_STATUS"
                     v-model:value="formModel.taskLabel"
-                    placeholder="请选择任务状态"
+                    placeholder="请选择任务标签"
                     width="100%"
                     :disabled="disabledStatus"
                   />
@@ -79,44 +79,50 @@
 
           <div class="steps-content">
             <a-button type="primary" @click="handleAdd" style="margin-bottom: 8px">分配任务</a-button>
-            <a-table :pagination="false" :columns="columns" :data-source="scheduleList" bordered>
-              <template v-for="col in ['positionStaff', 'planDays', 'planStartDate', 'planEndDate', 'settlementDays']" #[col]="{ index }" :key="col">
-                <div>
-                  <template v-if="col === 'positionStaff'">
-                    <a-input
-                      v-model:value="scheduleList[index].positionStaffA"
-                      placeholder="请选择岗位人员"
-                      @click="showSelectUser('deliveryManager', index)"
-                      readonly
-                    />
-                    <EmployeeTableSelectModal
-                      :ref="(el) => (selectDeliveryManagerRef[index] = el)"
-                      type="radio"
-                      @selectDataList="selectedUser('deliveryManager', index, $event)"
-                    />
-                  </template>
-                  <template v-else-if="col === 'planStartDate'">
-                    <a-date-picker v-model:value="scheduleList[index][col]" style="margin: -5px 0" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
-                  </template>
-                  <template v-else-if="col === 'planEndDate'">
-                    <a-date-picker v-model:value="scheduleList[index][col]" style="margin: -5px 0" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
-                  </template>
-                  <template v-else-if="col === 'planDays'">
-                    <a-input v-model:value="scheduleList[index][col]" style="margin: -5px 0" />
-                  </template>
-                  <template v-else>
-                    <a-input v-model:value="scheduleList[index][col]" style="margin: -5px 0" />
-                  </template>
-                </div>
-              </template>
-              <template #operation="{ index }">
-                <div class="editable-row-operations">
-                  <span>
-                    <a @click="onDelete(index)">删除</a>
-                  </span>
-                </div>
-              </template>
-            </a-table>
+            <a-form-item name="children" class="smart-query-form-item">
+              <a-table :pagination="false" :columns="columns" :data-source="scheduleList" bordered>
+                <template
+                  v-for="col in ['positionStaff', 'planDays', 'planStartDate', 'planEndDate', 'settlementDays']"
+                  #[col]="{ index }"
+                  :key="col"
+                >
+                  <div>
+                    <template v-if="col === 'positionStaff'">
+                      <a-input
+                        v-model:value="scheduleList[index].positionStaffA"
+                        placeholder="请选择岗位人员"
+                        @click="showSelectUser('deliveryManager', index)"
+                        readonly
+                      />
+                      <EmployeeTableSelectModal
+                        :ref="(el) => (selectDeliveryManagerRef[index] = el)"
+                        type="radio"
+                        @selectDataList="selectedUser('deliveryManager', index, $event)"
+                      />
+                    </template>
+                    <template v-else-if="col === 'planStartDate'">
+                      <a-date-picker v-model:value="scheduleList[index][col]" style="margin: -5px 0" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
+                    </template>
+                    <template v-else-if="col === 'planEndDate'">
+                      <a-date-picker v-model:value="scheduleList[index][col]" style="margin: -5px 0" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
+                    </template>
+                    <template v-else-if="col === 'planDays'">
+                      <a-input v-model:value="scheduleList[index][col]" style="margin: -5px 0" />
+                    </template>
+                    <template v-else>
+                      <a-input v-model:value="scheduleList[index][col]" style="margin: -5px 0" />
+                    </template>
+                  </div>
+                </template>
+                <template #operation="{ index }">
+                  <div class="editable-row-operations">
+                    <span>
+                      <a @click="onDelete(index)">删除</a>
+                    </span>
+                  </div>
+                </template>
+              </a-table>
+            </a-form-item>
           </div>
         </div>
       </div>
@@ -140,6 +146,15 @@
   const disabledStatus = ref(false);
   const router = useRouter();
 
+  const formRules = {
+    taskName: [{ required: true, message: '请输入任务名称', trigger: 'change' }],
+    taskType: [{ required: true, message: '请选择任务类型', trigger: 'change' }],
+    taskLabel: [{ required: true, message: '请选择任务标签', trigger: 'change' }],
+    taskLinks: [{ required: true, message: '请选择需求链接', trigger: 'change' }],
+    taskRemark: [{ required: true, message: '请选择任务说明', trigger: 'change' }],
+    children: [{ required: true, message: '请分配任务', trigger: 'change' }],
+  };
+
   onMounted(() => {
     reset();
     if (query.taskId) {
@@ -217,7 +232,7 @@
     scheduleList.value.forEach((item) => {
       const { createTime, createUserId, updateTime, updateUserId, ...restItem } = item;
       formData.push(restItem);
-    })
+    });
     formModel.children = formData;
     formModel.taskResource = 'personal';
     formModel.auditState = auditState;