فهرست منبع

回访完成

1
mo 2 سال پیش
والد
کامیت
68b445103d

+ 2 - 0
src/components/install.js

@@ -19,6 +19,7 @@ import auth from '@/components/Auth'
 import filterSearch from '@/components/filter-search'
 import singeFileUpload from '@/components/singe-file-upload'
 import Tooltip from '@/components/Tooltip'
+import uploadImageList from '@/components/uploadImageList'
 export default {
   install(Vue) {
     Vue.component(saveform.name, saveform)
@@ -37,5 +38,6 @@ export default {
     Vue.component(filterSearch.name, filterSearch)
     Vue.component(singeFileUpload.name, singeFileUpload)
     Vue.component(Tooltip.name, Tooltip)
+    Vue.component(uploadImageList.name,uploadImageList)
   }
 }

+ 222 - 0
src/components/uploadImageList/index.vue

@@ -0,0 +1,222 @@
+<template>
+  <!-- :before-upload="beforeUpload"     :headers="headers"    action="/api-web/uploadFile"-->
+  <div>
+    <el-upload
+      :action="ossUploadUrl"
+      :data="dataObj"
+      :on-preview="handlePictureCardPreview"
+      :show-file-list="false"
+      multiple
+      accept=".png, .jpg, .jpeg, .gif"
+      :before-upload="beforeUpload"
+      :on-success="successed"
+      :on-remove="handleRemove"
+      :on-exceed="handError"
+      :limit="max"
+    >
+      <el-button :loading="uploading" type="primary">上传图片</el-button>
+       <div v-if="max" class="el-upload__tip" slot="tip">最多只能上传{{max}}张图片</div>
+    </el-upload>
+    <div class="img-container">
+      <div class="list" v-if="uploaded.length > 0">
+        <div v-for="(item, index) in uploaded" :key="item.url" class="item">
+          <div class="ctrl-bar">
+            <i class="el-icon-circle-close" @click="remove(index)"></i>
+          </div>
+          <el-image
+            :src="item.url"
+            :preview-src-list="uploaded.map((item) => item.url)"
+            class="img"
+          >
+          </el-image>
+          <!-- <el-input
+            v-model="item.name"
+            placeholder="请输入图片名称"
+            clearable
+          /> -->
+        </div>
+      </div>
+      <empty v-else />
+    </div>
+  </div>
+</template>
+
+<script>
+import copy from "copy-to-clipboard";
+import { getToken } from "@/utils/auth";
+import load from "@/utils/loading";
+import { policy } from "@/api/appTenant";
+export default {
+  name: "uploadImageList",
+  props: {
+    buttonText: {
+      type: String,
+      default: "点击上传",
+    },
+    tips: {
+      type: String,
+      default: "",
+    },
+    uploaded: {
+      type: Array,
+      default: ()=>[],
+    },
+    accept: {
+      type: String,
+      default: "",
+    },
+    max: {
+      type: Number,
+      default: 5,
+    },
+    bucket_name: {
+      type: String,
+      default: "daya",
+    },
+  },
+  watch: {
+    value: {
+      handler() {
+        if (this.value) {
+          this.filelist = [
+            {
+              name: this.value,
+              url: this.value,
+            },
+          ];
+        } else {
+          this.remove();
+        }
+      },
+      immediate: true,
+    },
+  },
+  data() {
+    return {
+      filelist: [],
+      headers: {
+        Authorization: getToken(),
+      },
+      ossUploadUrl: "https://ks3-cn-beijing.ksyuncs.com/" + this.bucket_name,
+      dataObj: {
+        policy: "",
+        signature: "",
+        key: "",
+        KSSAccessKeyId: "",
+        // dir: "",
+        acl: "public-read",
+        name: "",
+        // bucket_name: props.bucket_name
+      },
+        uploading:false
+    };
+  },
+  methods: {
+    async beforeUpload(file) {
+      console.log(file)
+      this.uploading = true;
+      try {
+        let fileName = file.name.replaceAll(" ", "_");
+
+        let key = new Date().getTime() + fileName;
+        file.key = key;
+        let obj = {
+          filename: fileName,
+          bucketName: this.bucket_name,
+          postData: {
+            filename: fileName,
+            acl: "public-read",
+            key: key,
+            unknowValueField: [],
+          },
+        };
+
+        const res = await policy(obj);
+        this.dataObj = {
+          policy: res.data.policy,
+          signature: res.data.signature,
+          key: key,
+          KSSAccessKeyId: res.data.kssAccessKeyId,
+          // dir: "",
+          acl: "public-read",
+          name: fileName,
+          // bucket_name: props.bucket_name
+        };
+      } catch (e) {
+        console.log(e);
+      }
+      return true;
+    },
+    successed(response, file, fileList) {
+      this.uploading = false;
+      let url = this.ossUploadUrl + "/" + file.raw.key;
+      if (url) {
+        this.uploaded.push({
+          url,
+          name: file.name.split(".").shift(),
+          clientShow: "YES",
+        });
+      } else {
+        this.$message.error(res.data?.message || res.msg || "上传失败");
+      }
+      console.log(response, file, fileList);
+    },
+    handleRemove(file, fileList) {
+      console.log(file, fileList);
+    },
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = true;
+    },
+    remove(index) {
+      this.uploaded.splice(index, 1);
+    },
+    handError(files, fileList){
+      this.$message.error(`当前限制选择 ${this.max} 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
+    }
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.upload-text {
+  display: inline-block;
+  width: 100%;
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow: ellipsis;
+}
+.dialog-footer {
+  text-align: right;
+}
+.img-container {
+  margin: 10px auto;
+}
+.item {
+  width: 150px;
+  margin-top: 10px;
+  margin-right: 10px;
+  display: inline-block;
+  position: relative;
+}
+.img {
+  width: 150px;
+  height: 150px;
+}
+.ctrl-bar {
+  background-color: rgba(0, 0, 0, 0.45);
+  height: 30px;
+  position: absolute;
+  top: 0;
+  width: 100%;
+  z-index: 1;
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  padding: 0 15px;
+  i {
+    color: #fff;
+    cursor: pointer;
+  }
+}
+</style>

+ 1 - 1
src/views/main/studentLeaveList.vue

@@ -118,7 +118,7 @@
 
     <el-dialog
       title="新增回访"
-      width="500px"
+      width="760px"
       :visible.sync="visitVisible"
       append-to-body
     >

+ 5 - 1
src/views/returnVisitManager/api.js

@@ -14,6 +14,10 @@ export function addVisit (data) {
   return request({
     url: api + '/visit/add',
     method: 'post',
-    data: qs.stringify(data)
+    data,
+    requestType:'json',
+    headers: {
+      'content-type': 'application/json'
+    },
   })
 }

+ 101 - 28
src/views/returnVisitManager/returnVisitList.vue

@@ -114,10 +114,29 @@
               <copy-text>{{ scope.row.studentName }}</copy-text>
             </template>
           </el-table-column>
+
           <el-table-column align="center" prop="type" label="回访类型">
           </el-table-column>
           <el-table-column align="center" prop="purpose" label="回访目的">
           </el-table-column>
+
+          <el-table-column align="center" prop="name" label="回访图片">
+            <template slot-scope="scope">
+              <div class="flexBox">
+                <el-image
+                  v-if="scope.row.attachments"
+                  style="width: 60px; height: 60px"
+                  fit="cover"
+                  :src="scope.row.attachments.split(',')[0]"
+                  :previewSrcList="scope.row.attachments.split(',')"
+                >
+                </el-image>
+                <p v-if="scope.row.attachments.split(',').length - 1 > 0">
+                  +{{ scope.row.attachments.split(",").length - 1 }}
+                </p>
+              </div>
+            </template>
+          </el-table-column>
           <el-table-column align="center" prop="visitTime" label="回访时间">
             <template slot-scope="scope">
               <div>
@@ -149,36 +168,51 @@
     </div>
     <el-dialog
       title="回访详情"
-      width="700px"
+      width="740px"
       v-if="detailVisible"
       :visible.sync="detailVisible"
     >
-      <descriptions :column="2" v-if="activeRow" class="returnDialog">
-        <descriptions-item label="老师姓名:">{{
-          activeRow.teacherName
-        }}</descriptions-item>
-        <descriptions-item label="所属分部:">{{
-          activeRow.organName
-        }}</descriptions-item>
-        <descriptions-item label="角色:">{{
-          activeRow.visiterType | visiterType
-        }}</descriptions-item>
-        <descriptions-item label="学生姓名:">{{
-          activeRow.studentName
-        }}</descriptions-item>
-        <descriptions-item label="回访类型:">{{
-          activeRow.type
-        }}</descriptions-item>
-        <descriptions-item label="回访目的:">{{
-          activeRow.purpose
-        }}</descriptions-item>
-        <descriptions-item label="回访情况:" :span="6">{{
-          activeRow.overview
-        }}</descriptions-item>
-        <descriptions-item label="家长反馈" :span="6">{{
-          activeRow.feedback
-        }}</descriptions-item>
-      </descriptions>
+      <div>
+        <descriptions :column="2" v-if="activeRow" class="returnDialog">
+          <descriptions-item label="老师姓名:">{{
+            activeRow.teacherName
+          }}</descriptions-item>
+          <descriptions-item label="所属分部:">{{
+            activeRow.organName
+          }}</descriptions-item>
+          <descriptions-item label="角色:">{{
+            activeRow.visiterType | visiterType
+          }}</descriptions-item>
+          <descriptions-item label="学生姓名:">{{
+            activeRow.studentName
+          }}</descriptions-item>
+          <descriptions-item label="回访类型:">{{
+            activeRow.type
+          }}</descriptions-item>
+          <descriptions-item label="回访目的:">{{
+            activeRow.purpose
+          }}</descriptions-item>
+          <descriptions-item label="回访情况:" :span="6">{{
+            activeRow.overview
+          }}</descriptions-item>
+          <descriptions-item label="家长反馈" :span="6">{{
+            activeRow.feedback
+          }}</descriptions-item>
+          <descriptions-item label="回访图片" :span="6">
+            <div class="list" v-if="imageList.length > 0">
+              <div v-for="item in imageList" :key="item.url" class="item">
+                <el-image
+                  :src="item"
+                  :preview-src-list="imageList.map((item) => item)"
+                  class="img"
+                >
+                </el-image>
+              </div>
+            </div>
+            <empty v-else />
+          </descriptions-item>
+        </descriptions>
+      </div>
     </el-dialog>
   </div>
 </template>
@@ -213,6 +247,7 @@ export default {
         page_size: [10, 20, 40, 50], // 选择限制显示条数
       },
       tableList: [],
+      imageList: [],
       detailVisible: false,
       activeRow: null,
     };
@@ -240,7 +275,7 @@ export default {
     this.getList();
     if (this.$route.query.search || this.$route.query.timer) {
       // console.log( )
-      console.log('进来了')
+      console.log("进来了");
       resetQuery(this, { timer: undefined, search: undefined });
     }
   },
@@ -299,6 +334,7 @@ export default {
     },
     lookDetail(row) {
       this.activeRow = row;
+      this.imageList = this.activeRow.attachments.split(",");
       this.detailVisible = true;
     },
     changeTimer(val) {
@@ -315,6 +351,7 @@ export default {
     detailVisible(val) {
       if (!val) {
         this.activeRow = null;
+        this.imageList = [];
       }
     },
   },
@@ -337,4 +374,40 @@ export default {
     }
   }
 }
+.flexBox {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+}
+
+.img-container {
+  margin: 10px auto;
+}
+.item {
+  width: 150px;
+  margin-top: 10px;
+  margin-right: 10px;
+  display: inline-block;
+  position: relative;
+}
+.img {
+  width: 150px;
+  height: 150px;
+}
+.ctrl-bar {
+  background-color: rgba(0, 0, 0, 0.45);
+  height: 30px;
+  position: absolute;
+  top: 0;
+  width: 100%;
+  z-index: 1;
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  padding: 0 15px;
+  i {
+    color: #fff;
+    cursor: pointer;
+  }
+}
 </style>

+ 14 - 2
src/views/smallStudentManager/components/addVisit.vue

@@ -64,6 +64,13 @@
           >
         </el-radio-group>
       </el-form-item>
+
+      <el-form-item label="回访图片">
+        <div   style="width: 80% !important">
+            <uploadImageList :uploaded="visitForm.attachments"/>
+        </div>
+
+      </el-form-item>
       <el-form-item label="原因" prop="feedback" :rules="[{ required: isRequire, message: '请输入家长反馈内容' }]">
         <el-input
           type="textarea"
@@ -114,7 +121,8 @@ export default {
         feedback: "",
         studentName: "",
         feedbackType: "",
-        feedbackTypeDesc:""
+        feedbackTypeDesc:"",
+        attachments:[]
       },
       visitRules: {
         overview: [{ required: true, message: "请输入学生近况" }],
@@ -135,7 +143,7 @@ export default {
     };
   },
   mounted() {
-    console.log(this.useVisitType,'useVisitType',this.detail)
+
     if (this.isMainGo) {
       this.visitChiose = visitChiose1;
       this.$set(this.visitForm, "visitType", ["常规回访", "考勤申诉"]);
@@ -173,6 +181,9 @@ export default {
       this.$refs.visitForm.validate((res) => {
         if (res) {
           const { visitType, ...rest } = this.visitForm;
+          let attachmentsList = this.visitForm.attachments.map(item=>{
+            return item.url
+          })
           const data = {
             ...rest,
             objectId: this.detail.id,
@@ -181,6 +192,7 @@ export default {
             studentId: this.studentId,
             type: visitType[0],
             purpose: visitType[1],
+            attachments:attachmentsList.join(',')
           };
           addVisit(cleanDeep(data)).then((res) => {
             if (res.code === 200) {

+ 1 - 1
src/views/stuRecodeManager/index.vue

@@ -366,7 +366,7 @@
           :page-sizes="rules.page_size"
           @pagination="getList"
         />
-        <el-dialog title="新增回访" width="500px" :visible.sync="visitVisible">
+        <el-dialog title="新增回访" width="760px" :visible.sync="visitVisible">
           <visit
             v-if="visitVisible && detail"
             :detail="detail"

+ 1 - 1
src/views/studentManager/memberList.vue

@@ -231,7 +231,7 @@
     <!-- 新增回访 -->
     <el-dialog
       title="新增回访"
-      width="500px"
+      width="760px"
       :visible.sync="visitVisible"
       append-to-body
     >

+ 1 - 1
src/views/teamBuild/forecastName.vue

@@ -354,7 +354,7 @@
     <!-- 回访记录 -->
     <el-dialog
       title="新增回访"
-      width="600px"
+      width="760px"
        v-if="visitVisible"
       :close-on-click-modal="false"
       :visible.sync="visitVisible"

+ 1 - 1
src/views/teamBuild/signupList.vue

@@ -1059,7 +1059,7 @@
     <!-- 回访记录 -->
     <el-dialog
       title="新增回访"
-      width="500px"
+      width="760px"
       v-if="visitVisiable"
       :close-on-click-modal="false"
       :visible.sync="visitVisiable"

+ 3 - 3
src/views/teamDetail/componentCourse/studentRollCall.vue

@@ -81,14 +81,14 @@
           <template slot-scope="scope">
             <div>
               <el-button
-               
+
                 type="text"
                 @click="addVisit(scope.row)"
                 v-if="!scope.row.visitFlag&&permission('visit/add?page=teamCourseList')"
                 >新增回访</el-button
               >
                 <el-button
-                 
+
                 type="text"
                 @click="lookVisit(scope.row)"
                 v-if="(scope.row.visitFlag)&&permission('visit/queryPage?page=teamCourseList')"
@@ -107,7 +107,7 @@
     </div>
     <el-dialog
       title="新增回访"
-      width="500px"
+      width="760px"
       :visible.sync="visitVisible"
       append-to-body
     >

+ 1 - 1
src/views/teamDetail/components/studentList.vue

@@ -879,7 +879,7 @@
     </el-dialog>
     <el-dialog
       title="新增回访"
-      width="500px"
+      width="760px"
       :close-on-click-modal="false"
       :visible.sync="visitVisiable"
       v-if="visitVisiable"

+ 1 - 1
src/views/withdrawal-application/index.vue

@@ -292,7 +292,7 @@
         @submited="FetchList"
       />
     </el-dialog> -->
-    <el-dialog title="新增回访" width="500px" :visible.sync="visitVisible">
+    <el-dialog title="新增回访" width="760px" :visible.sync="visitVisible">
       <visit
         v-if="visitVisible && detail"
         :detail="detail"

+ 10 - 0
src/views/withdrawal-application/modals/visit.vue

@@ -70,6 +70,11 @@
           show-word-limit
         ></el-input>
       </el-form-item>
+      <el-form-item label="回访图片">
+        <div style="width: 80% !important">
+          <uploadImageList :uploaded="visitForm.attachments" />
+        </div>
+      </el-form-item>
     </el-form>
     <div
       slot="footer"
@@ -123,6 +128,7 @@ export default {
         visitType: "",
         feedback: "",
         studentName: "",
+        attachments: [],
       },
       visitRules: {
         overview: [{ required: true, message: "请输入学生近况" }],
@@ -170,6 +176,9 @@ export default {
       this.$refs.visitForm.validate((res) => {
         if (res) {
           const { visitType, ...rest } = this.visitForm;
+          let attachmentsList = this.visitForm.attachments.map((item) => {
+            return item.url;
+          });
           const data = {
             ...rest,
             objectId: this.detail.id,
@@ -178,6 +187,7 @@ export default {
             studentId: this.studentId,
             type: visitType[0],
             purpose: visitType[1],
+               attachments:attachmentsList.join(',')
           };
           addVisit(cleanDeep(data)).then((res) => {
             if (res.code === 200) {