Sfoglia il codice sorgente

Merge branch 'master' of https://gitee.com/vansfa/rt_companyUI

wansfa 1 anno fa
parent
commit
274ce04ff7

+ 1 - 0
package.json

@@ -56,6 +56,7 @@
     "nprogress": "0.2.0",
     "path-to-regexp": "2.4.0",
     "qrcodejs2": "0.0.2",
+    "qrious": "^4.0.2",
     "quill": "1.3.7",
     "screenfull": "4.2.0",
     "sortablejs": "1.8.4",

+ 60 - 0
src/api/qw/account.js

@@ -0,0 +1,60 @@
+import request from '@/utils/request'
+
+// 查询企微功能账号管理列表
+export function listAccount(query) {
+  return request({
+    url: '/qw/account/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询企微功能账号管理详细
+export function getAccount(id) {
+  return request({
+    url: '/qw/account/' + id,
+    method: 'get'
+  })
+}
+
+// 新增企微功能账号管理
+export function addAccount(data) {
+  return request({
+    url: '/qw/account',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改企微功能账号管理
+export function updateAccount(data) {
+  return request({
+    url: '/qw/account',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除企微功能账号管理
+export function delAccount(id) {
+  return request({
+    url: '/qw/account/' + id,
+    method: 'delete'
+  })
+}
+
+// 导出企微功能账号管理
+export function exportAccount(query) {
+  return request({
+    url: '/qw/account/export',
+    method: 'get',
+    params: query
+  })
+}
+//根据账号获取设备id
+export function getDeviceId(userName) {
+  return request({
+    url: '/qw/account/getDeviceId/' + userName,
+    method: 'get'
+  })
+}

+ 11 - 0
src/api/qw/login.js

@@ -0,0 +1,11 @@
+import request from '@/utils/request'
+
+
+//获取二维码
+export function getQrCode(deviceId) {
+  return request({
+    url: '/qw/login/getQrCode/' + deviceId,
+    method: 'get'
+  })
+}
+

+ 8 - 0
src/api/store/storeOrder.js

@@ -112,3 +112,11 @@ export function bindCustomer(data) {
   })
 }
 
+export function uploadCredentials(data) {
+  return request({
+    url: '/store/storeOrder/uploadCredentials',
+    method: 'post',
+    data: data
+  })
+}
+

+ 226 - 0
src/components/ImageUpload/index.vue

@@ -0,0 +1,226 @@
+<template>
+  <div class="component-upload-image">
+    <el-upload
+      multiple
+      :action="uploadImgUrl"
+      list-type="picture-card"
+      :on-success="handleUploadSuccess"
+      :before-upload="handleBeforeUpload"
+      :limit="limit"
+      :on-error="handleUploadError"
+      :on-exceed="handleExceed"
+      ref="imageUpload"
+      :on-remove="handleDelete"
+      :show-file-list="true"
+      :file-list="fileList"
+      :on-preview="handlePictureCardPreview"
+      :class="{hide: this.fileList.length >= this.limit}"
+      :data="{type: 1}"
+    >
+      <i class="el-icon-plus"></i>
+    </el-upload>
+
+    <!-- 上传提示 -->
+    <div class="el-upload__tip" slot="tip" v-if="showTip">
+      请上传
+      <template v-if="fileSize"> 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b> </template>
+      <template v-if="fileType"> 格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template>
+      的文件
+    </div>
+
+    <el-dialog
+      :visible.sync="dialogVisible"
+      title="预览"
+      width="800"
+      append-to-body
+    >
+      <img
+        :src="dialogImageUrl"
+        style="display: block; max-width: 100%; margin: 0 auto"
+      />
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getToken } from "@/utils/auth";
+import FormMakingCommon from "form-making";
+
+export default {
+  props: {
+    value: [String, Object, Array],
+    // 图片数量限制
+    limit: {
+      type: Number,
+      default: 5,
+    },
+    // 大小限制(MB)
+    fileSize: {
+       type: Number,
+      default: 5,
+    },
+    // 文件类型, 例如['png', 'jpg', 'jpeg']
+    fileType: {
+      type: Array,
+      default: () => ["png", "jpg", "jpeg"],
+    },
+    // 是否显示提示
+    isShowTip: {
+      type: Boolean,
+      default: true
+    }
+  },
+  data() {
+    return {
+      number: 0,
+      uploadList: [],
+      dialogImageUrl: "",
+      dialogVisible: false,
+      hideUpload: false,
+      baseUrl: process.env.VUE_APP_BASE_API,
+      uploadImgUrl:process.env.VUE_APP_BASE_API+"/common/uploadOSS", // 上传的图片服务器地址
+      headers: {
+        Authorization: "Bearer " + getToken(),
+      },
+      fileList: []
+    };
+  },
+  watch: {
+    value: {
+      handler(val) {
+        if (val) {
+          // 首先将值转为数组
+          const list = Array.isArray(val) ? val : this.value.split(',');
+          // 然后将数组转为对象数组
+          this.fileList = list.map(item => {
+            if (typeof item === "string") {
+              item = { name: item, url: item };
+            }
+            return item;
+          });
+        } else {
+          this.fileList = [];
+          return [];
+        }
+      },
+      deep: true,
+      immediate: true
+    }
+  },
+  computed: {
+    // 是否显示提示
+    showTip() {
+      return this.isShowTip && (this.fileType || this.fileSize);
+    },
+  },
+  methods: {
+    // 上传前loading加载
+    handleBeforeUpload(file) {
+      let isImg = false;
+      if (this.fileType.length) {
+        let fileExtension = "";
+        if (file.name.lastIndexOf(".") > -1) {
+          fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1);
+        }
+        isImg = this.fileType.some(type => {
+          if (file.type.indexOf(type) > -1) return true;
+          if (fileExtension && fileExtension.indexOf(type) > -1) return true;
+          return false;
+        });
+      } else {
+        isImg = file.type.indexOf("image") > -1;
+      }
+
+      if (!isImg) {
+        this.$message.error(`文件格式不正确, 请上传${this.fileType.join("/")}图片格式文件!`);
+        return false;
+      }
+      if (this.fileSize) {
+        const isLt = file.size / 1024 / 1024 < this.fileSize;
+        if (!isLt) {
+          this.$message.error(`上传头像图片大小不能超过 ${this.fileSize} MB!`);
+          return false;
+        }
+      }
+      // this.$message.loading("正在上传图片,请稍候...");
+      
+      this.number++;
+    },
+    // 文件个数超出
+    handleExceed() {
+      this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
+    },
+    // 上传成功回调
+    handleUploadSuccess(res, file) {
+      console.log(res)
+      console.log(file)
+      if (res.code === 200) {
+        this.uploadList.push({ name: file.name, url: res.url });
+        this.uploadedSuccessfully();
+      } else {
+        this.number--;
+        this.$message.closeLoading();
+        this.$message.error(res.msg);
+        this.$refs.imageUpload.handleRemove(file);
+        this.uploadedSuccessfully();
+      }
+    },
+    // 删除图片
+    handleDelete(file) {
+      const findex = this.fileList.map(f => f.name).indexOf(file.name);
+      if(findex > -1) {
+        this.fileList.splice(findex, 1);
+        this.$emit("input", this.listToString(this.fileList));
+      }
+    },
+    // 上传失败
+    handleUploadError() {
+      this.$message.error("上传图片失败,请重试");
+      this.$message.closeLoading();
+    },
+    // 上传结束处理
+    uploadedSuccessfully() {
+      if (this.number > 0 && this.uploadList.length === this.number) {
+        this.fileList = this.fileList.concat(this.uploadList);
+        this.uploadList = [];
+        this.number = 0;
+        this.$emit("input", this.listToString(this.fileList));
+        //this.$message.closeLoading();
+      }
+    },
+    // 预览
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url;
+      this.dialogVisible = true;
+    },
+    // 对象转成指定字符串分隔
+    listToString(list, separator) {
+      let strs = "";
+      separator = separator || ",";
+      for (let i in list) {
+        if (list[i].url) {
+          strs += list[i].url.replace(this.baseUrl, "") + separator;
+        }
+      }
+      return strs != '' ? strs.substr(0, strs.length - 1) : '';
+    }
+  }
+};
+</script>
+<style scoped lang="scss">
+// .el-upload--picture-card 控制加号部分
+::v-deep.hide .el-upload--picture-card {
+    display: none;
+}
+// 去掉动画效果
+::v-deep .el-list-enter-active,
+::v-deep .el-list-leave-active {
+    transition: all 0s;
+}
+
+::v-deep .el-list-enter, .el-list-leave-active {
+    opacity: 0;
+    transform: translateY(0);
+}
+</style>
+

+ 3 - 1
src/main.js

@@ -15,6 +15,8 @@ import router from './router'
 import permission from './directive/permission'
 
 import VueClipboard from 'vue-clipboard2'
+//图片上传组件
+import ImageUpload from "@/components/ImageUpload"
 
 import './assets/icons' // icon
 import './permission' // permission control
@@ -35,7 +37,7 @@ Vue.use(VueClipboard)
 
 Vue.use(FormMaking)
 // 全局方法挂载
-
+Vue.component('ImageUpload',ImageUpload)
 import audio from 'vue-mobile-audio'
 Vue.use(audio)
 

+ 75 - 1
src/views/crm/customer/index.vue

@@ -191,6 +191,15 @@
               v-hasPermi="['crm:customer:export']"
             >导出</el-button>
           </el-col>
+          <el-col :span="1.5">
+          <el-button
+            type="warning"
+            icon="el-icon-upload2"
+            size="mini"
+            @click="handleImport"
+            v-hasPermi="['crm:customer:importVisit']"
+          >导入跟进阶段</el-button>
+        </el-col>
         <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
         </el-row>
         <el-tabs type="card" v-model="queryParams.isReceive" @tab-click="handleClick">
@@ -302,12 +311,34 @@
     <el-dialog :title="assign.title" :visible.sync="assign.open" width="800px" append-to-body>
         <assign-user  ref="assignUser" @close="closeAssign"   />
     </el-dialog>
+    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+        <el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
+          <i class="el-icon-upload"></i>
+          <div class="el-upload__text">
+            将文件拖到此处,或
+            <em>点击上传</em>
+          </div>
+          <div class="el-upload__tip" slot="tip">
+            <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
+          </div>
+          <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
+        </el-upload>
+        <div slot="footer" class="dialog-footer">
+          <el-button type="primary" @click="submitFileForm">确 定</el-button>
+          <el-button @click="upload.open = false">取 消</el-button>
+        </div>
+    </el-dialog>
+    <el-dialog title="导入结果" :close-on-press-escape="false" :close-on-click-modal="false" :visible.sync="importMsgOpen" width="500px" append-to-body>
+       <div class="import-msg" v-html="importMsg">
+       </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
  
-import { assignToUser,recover,receive,getCustomerList ,addCustomer,updateCustomer,getCustomerDetails,exportCustomer } from "@/api/crm/customer";
+import { assignToUser,recover,receive,getCustomerList ,addCustomer,updateCustomer,getCustomerDetails,exportCustomer,importVisitTemplate } from "@/api/crm/customer";
+import { getToken } from "@/utils/auth";
 import customerDetails from '../components/customerDetails.vue';
 import {getCitys} from "@/api/store/city";
 import { treeselect } from "@/api/company/companyDept";
@@ -323,6 +354,20 @@ export default {
   components: {assignUser,customerAssignList,addBatchSms,editSource, customerDetails,Treeselect,customerSource },
   data() {
     return {
+      upload: {
+        // 是否显示弹出层(用户导入)
+        open: false,
+        // 弹出层标题(用户导入)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 设置上传的请求头部
+        headers: { Authorization: "Bearer " + getToken() },
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + "/crm/customer/importVisitData",
+      },
+      importMsgOpen:false,
+      importMsg:"",
       tagIds:[],
       tagsOptions:[],
       assignList:{
@@ -811,6 +856,35 @@ export default {
           this.download(response.msg);
         }).catch(function() {});
     },
+     /** 导入按钮操作 */
+     handleImport() {
+      this.upload.title = "客户跟进情况导入";
+      this.upload.open = true;
+
+    },
+     /** 下载模板操作 */
+     importTemplate() {
+      importVisitTemplate().then((response) => {
+        this.download(response.msg);
+      });
+    },
+    // 文件上传中处理
+    handleFileUploadProgress(event, file, fileList) {
+      this.upload.isUploading = true;
+    },
+    // 文件上传成功处理
+    handleFileSuccess(response, file, fileList) {
+      this.upload.open = false;
+      this.upload.isUploading = false;
+      this.$refs.upload.clearFiles();
+      this.importMsgOpen=true;
+      this.importMsg=response.msg
+      this.getList();
+    },
+     // 提交上传文件
+    submitFileForm() {
+      this.$refs.upload.submit();
+    },
   }
 };
 </script>

+ 1 - 77
src/views/crm/customer/my.vue

@@ -143,15 +143,6 @@
           v-hasPermi="['crm:customer:sendBatchSms']"
         >批量发送短信</el-button>
       </el-col>
-      <el-col :span="1.5">
-          <el-button
-            type="warning"
-            icon="el-icon-upload2"
-            size="mini"
-            @click="handleImport"
-            v-hasPermi="['crm:customer:importVisit']"
-          >导入跟进阶段</el-button>
-        </el-col>
       <el-col :span="1.5">
         <el-button
           type="warning"
@@ -278,38 +269,14 @@
     <el-dialog :title="addVisitStatus.title" :visible.sync="addVisitStatus.open" width="600px" append-to-body>
         <add-visit-status ref="visitStatus" @close="closeVisitStatus()"></add-visit-status>
     </el-dialog>
-
-    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
-        <el-upload ref="upload" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag>
-          <i class="el-icon-upload"></i>
-          <div class="el-upload__text">
-            将文件拖到此处,或
-            <em>点击上传</em>
-          </div>
-          <div class="el-upload__tip" slot="tip">
-            <el-link type="info" style="font-size:12px" @click="importTemplate">下载模板</el-link>
-          </div>
-          <div class="el-upload__tip" style="color:red" slot="tip">提示:仅允许导入“xls”或“xlsx”格式文件!</div>
-        </el-upload>
-        <div slot="footer" class="dialog-footer">
-          <el-button type="primary" @click="submitFileForm">确 定</el-button>
-          <el-button @click="upload.open = false">取 消</el-button>
-        </div>
-    </el-dialog>
-
-    <el-dialog title="导入结果" :close-on-press-escape="false" :close-on-click-modal="false" :visible.sync="importMsgOpen" width="500px" append-to-body>
-       <div class="import-msg" v-html="importMsg">
-       </div>
-    </el-dialog>
   </div>
 </template>
 
 <script>
-import { getMyCustomerList,recover,exportCustomer,importVisitTemplate  } from "@/api/crm/customer";
+import { getMyCustomerList,recover,exportCustomer  } from "@/api/crm/customer";
 import customerDetails from '../components/customerDetails.vue';
 import addVisit from '../components/addVisit.vue';
 import {getCitys} from "@/api/store/city";
-import { getToken } from "@/utils/auth";
 import addBatchSms from '../components/addBatchSms.vue';
 import editSource from '../components/editSource.vue';
 import addOrEditCustomer from '../components/addOrEditCustomer.vue';
@@ -362,20 +329,6 @@ export default {
         title:"分配客户",
         open:false,
       },
-      upload: {
-        // 是否显示弹出层(用户导入)
-        open: false,
-        // 弹出层标题(用户导入)
-        title: "",
-        // 是否禁用上传
-        isUploading: false,
-        // 设置上传的请求头部
-        headers: { Authorization: "Bearer " + getToken() },
-        // 上传的地址
-        url: process.env.VUE_APP_BASE_API + "/crm/customer/importVisitData",
-      },
-      importMsgOpen:false,
-      importMsg:"",
       assignForm: {
       },
       // 表单校验
@@ -734,35 +687,6 @@ export default {
           this.download(response.msg);
         }).catch(function() {});
     },
-     /** 导入按钮操作 */
-     handleImport() {
-      this.upload.title = "客户跟进情况导入";
-      this.upload.open = true;
-
-    },
-    /** 下载模板操作 */
-    importTemplate() {
-      importVisitTemplate().then((response) => {
-        this.download(response.msg);
-      });
-    },
-    // 文件上传中处理
-    handleFileUploadProgress(event, file, fileList) {
-      this.upload.isUploading = true;
-    },
-    // 文件上传成功处理
-    handleFileSuccess(response, file, fileList) {
-      this.upload.open = false;
-      this.upload.isUploading = false;
-      this.$refs.upload.clearFiles();
-      this.importMsgOpen=true;
-      this.importMsg=response.msg
-      this.getList();
-    },
-     // 提交上传文件
-    submitFileForm() {
-      this.$refs.upload.submit();
-    },
   }
 };
 </script>

+ 0 - 0
src/views/qw/components


+ 250 - 0
src/views/qw/qwAccounts/index.vue

@@ -0,0 +1,250 @@
+<template>
+  <div class="app-container">
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+        type="primary"
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['qw:account:add']"
+        >添加账号</el-button>
+      </el-col>
+    </el-row>
+    <el-table border v-loading="loading" :data="accountList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="序号"  width="55" type="index" align="center" />
+      <el-table-column label="账号id" align="center" prop="id" />
+      <el-table-column label="企微账号" align="center" prop="userName" />
+      <el-table-column label="姓名" align="center" prop="nickName" />
+      <el-table-column label="手机号码" align="center" prop="phone" />
+      <el-table-column label="审核状态" align="center" prop="isAudit" >
+          <template slot-scope="scope">
+              <el-tag prop="isAudit" v-for="(item, index) in isAuditOptions"    v-if="scope.row.isAudit==item.dictValue">{{item.dictLabel}}</el-tag>
+          </template>
+      </el-table-column>
+      <el-table-column width="500" label="关联设备id" align="center" prop="deviceId" />
+      <el-table-column label="备注" align="center" prop="remark" />
+      
+    </el-table>
+    
+    <!-- <pagination
+      v-show="total>0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    /> -->
+
+    <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="120px">
+        <el-form-item label="企微账号" prop="userName">
+          <el-input v-model="form.userName" placeholder="请输入企微账号"   />
+        </el-form-item>
+        <el-form-item label="手机号" prop="phone">
+          <el-input v-model="form.phone" placeholder="请输入手机号"   />
+        </el-form-item>
+        <el-form-item label="姓名" prop="nickName">
+          <el-input v-model="form.nickName" placeholder="请输入姓名"   />
+        </el-form-item>
+        <el-form-item label="备注" prop="remark">
+          <el-input v-model="form.remark"  type="textarea" :row="5"  />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listAccount, getAccount, delAccount, addAccount, auditAccount, exportAccount } from "@/api/qw/account";
+import { getCompanyList } from "@/api/company/company";
+
+export default {
+  name: "Account",
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 选中数组
+      ids: [],
+      companys:[],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      activeName:"1",
+      // 企微功能账号管理表格数据
+      accountList: [],
+      isAuditOptions:[],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        userName: null,
+        passWord: null,
+        phone: null,
+        email: null,
+        status: null,
+        realName: null,
+        nickName: null,
+        companyId: null,
+        deviceId: null,
+        deptId: null,
+        companyUserId: null,
+        isAudit: 0,
+      },
+      // 表单参数
+      form: {},
+      auditForm:{
+        id:null,
+        isAudit: null,
+        deviceId: null,
+      },
+      // 表单校验
+      rules: {
+        deviceId: [
+          { required: true, message: "关联设备id不能为空", trigger: "blur" }
+        ],
+        isAudit: [
+          { required: true, message: "是否审核不能为空", trigger: "blur" }
+        ],
+      }
+    };
+  },
+  created() {
+    this.getList();
+    getCompanyList().then(response => {
+      this.companys = response.data;
+    });
+    this.getDicts("common_audit").then((response) => {
+      this.isAuditOptions = response.data;
+    });
+  },
+  methods: {
+    /** 查询企微功能账号管理列表 */
+    getList() {
+      this.loading = true;
+      listAccount(this.queryParams).then(response => {
+        this.accountList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        userName: null,
+        passWord: null,
+        phone: null,
+        email: null,
+        createTime: null,
+
+        remark: null,
+        realName: null,
+        nickName: null,
+        companyId: null,
+        deviceId: null,
+        deptId: null,
+        companyUserId: null,
+        isAudit: null,
+        updateTime: null
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map(item => item.id)
+      this.single = selection.length!==1
+      this.multiple = !selection.length
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.reset();
+      this.open = true;
+      this.title = "添加企微功能账号管理";
+    },
+    
+    handleAudit(row) {
+      this.reset();
+      const id = row.id || this.ids
+      getAccount(id).then(response => {
+        this.form = response.data;
+        this.form.companyName = row.companyName;
+        this.form.companyUserName = row.companyUserName;
+        this.form.isAudit="1"
+        this.open = true;
+        this.title = "账号审核";
+      });
+    },
+   /** 提交按钮 */
+   submitForm() {
+      this.$refs["form"].validate(valid => {
+        if (valid) {
+          addAccount(this.form).then(response => {
+            if (response.code === 200) {
+              this.msgSuccess("审核成功");
+              this.open = false;
+              this.getList();
+            }
+          });
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$confirm('是否确认删除企微功能账号管理编号为"' + ids + '"的数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return delAccount(ids);
+        }).then(() => {
+          this.getList();
+          this.msgSuccess("删除成功");
+        }).catch(function() {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$confirm('是否确认导出所有企微功能账号管理数据项?', "警告", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning"
+        }).then(function() {
+          return exportAccount(queryParams);
+        }).then(response => {
+          this.download(response.msg);
+        }).catch(function() {});
+    }
+  }
+};
+</script>

+ 30 - 0
src/views/qw/qwContact/index.vue

@@ -0,0 +1,30 @@
+<template>
+  <div>
+    <img ref="imageElement" alt="Base64 Image">
+  </div>
+</template>
+
+<script>
+export default {
+  mounted() {
+    this.convertBase64ToImage();
+  },
+  methods: {
+    convertBase64ToImage() {
+      
+// Base64 编码
+
+      // 创建一个新的 Image 对象
+      const image = new Image();
+      
+      // 当图片加载完成时,将其赋值给 <img> 元素
+      image.onload = () => {
+        this.$refs.imageElement.src = image.src;
+      };
+      
+      // 设置 Image 对象的 src 属性为 Base64 数据
+      image.src = `data:image/jpeg;base64,${base64Data}`;
+    }
+  }
+};
+</script>

+ 129 - 0
src/views/qw/qwLogin/index.vue

@@ -0,0 +1,129 @@
+<template>
+  <div class="scan-login">
+    <el-row align="middle" justify="center">
+      <el-col :span="8">
+        <el-card class="scan-card" shadow="hover">
+          <div class="scan-card-content">
+            <h1 class="title">扫码登录</h1>
+            <el-input v-model="userName" placeholder="请输入账号" style="margin-bottom: 20px;"></el-input>
+            <el-button type="primary" @click="login" >登录</el-button>
+            <div class="qrcode-container" v-show="showQRCode">
+              <div>
+                <img ref="imageElement" alt="Base64 Image" style="width:250px,height:auto ;">
+              </div>
+            </div>
+          </div>
+        </el-card>
+      </el-col>
+    </el-row>
+  </div>
+</template>
+
+<script>
+import { getQrCode } from '@/api/qw/login';
+import { getDeviceId} from '@/api/qw/account';
+
+export default {
+  data() {
+    return {
+      userName: '', // 用户输入的账号
+      qrcode: null, // 二维码实例
+      loading: false, // 刷新按钮加载状态
+      deviceId: '', // 账号关联的 deviceId
+      showQRCode: false, // 是否显示二维码
+      errorMessage: '', // 错误信息
+      qrCode:'',
+    };
+  },
+  methods: {
+    login() {
+      const userName = this.userName;
+      getDeviceId(userName).then(response => {
+        this.deviceId = response.deviceId;
+      });
+      this.showQRCode = !!this.deviceId; // 根据 deviceId 控制是否显示二维码
+      if (this.showQRCode) {
+          // 获取二维码
+          getQrCode(this.deviceId).then(response => {
+            this.qrCode = response.data; 
+            const base64Data = this.qrCode; // Base64 编码
+            const image = new Image();
+            image.onload = () => {
+              this.$refs.imageElement.src = image.src;
+            };
+            image.src = `data:image/jpeg;base64,${base64Data}`;     
+          });
+        } else {
+          // deviceId 为空时显示错误提示
+          this.errorMessage = '请检查账号是否正确或是否审核通过';
+        }
+    },
+    // convertBase64ToImage(qrCode) {
+
+    //   const base64Data = qrCode; // Base64 编码
+
+    //   console.log(base64Data)
+    //   const image = new Image();
+    //   image.onload = () => {
+    //     this.$refs.imageElement.src = image.src;
+    //   };
+    //   image.src = `data:image/jpeg;base64,${base64Data}`;
+    // },
+    
+  },
+};
+</script>
+
+<style scoped>
+.scan-login {
+  height: 100vh;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.scan-card {
+  width: 400px;
+}
+
+.scan-card-content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: 20px;
+}
+
+.title {
+  font-size: 24px;
+  margin-bottom: 20px;
+}
+
+.qrcode-container {
+  position: relative;
+  text-align: center;
+}
+
+.qrcode {
+  display: inline-block;
+  margin-bottom: 10px;
+}
+
+.qrcode-refresh {
+  position: absolute;
+  bottom: 0;
+  left: 50%;
+  transform: translateX(-50%);
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+  color: #1890ff;
+}
+
+.qrcode-refresh i {
+  margin-right: 5px;
+}
+
+.qrcode-refresh:hover {
+  color: #40a9ff;
+}
+</style>

+ 68 - 5
src/views/store/components/productOrder.vue

@@ -17,11 +17,12 @@
         </span>
        
         <div class="operate-button-container" >
+          <el-button size="mini" @click="handleCertificates()"  v-hasPermi="['store:storeOrder:uploadCredentials']" >上传凭证</el-button>
           <el-button size="mini" @click="handleEditAddress()" v-if="order.status==0||order.status==1"  v-hasPermi="['store:storeOrder:editAddress']" >修改收货地址</el-button>
           <el-button size="mini" @click="handleBindCustomer()"  v-hasPermi="['store:storeOrder:bindCustomer']" >关联客户</el-button>
           <el-button size="mini" @click="editOrder()"  v-hasPermi="['store:storeOrder:edit']" >修改订单</el-button>
           <!-- <el-button size="mini" @click="handleEditUser()"  v-hasPermi="['users:user:edit']" >修改会员修改</el-button> -->
-          <el-button size="mini" v-if="order.customerId!=null&&order.customerId>0"  @click="handleCustomer()"    >查看客户详情</el-button>
+          <el-button size="mini" v-if="order.customerId!=null&&order.customerId>0"  @click="handleCustomer()"    >查看客户详情</el-button>         
         </div>
         <div class="operate-button-container"  v-hasPermi="['store:storeOrder:express']"  >
           <el-button size="mini" @click="showExpress()" >查看物流</el-button>
@@ -124,6 +125,21 @@
             </el-descriptions-item>
         
       </el-descriptions>
+      <div style="margin: 20px 0px"  v-if="order!=null">
+        <span class="font-small">
+          凭证信息
+        </span>
+      </div>
+      <el-image
+          v-if="this.certificates != null"
+          :src="certificates"
+          :preview-src-list="[certificates]"
+          :style="{ width: '100px', height: '100px' }"
+          @click.native="showImageDialog"
+        ></el-image>
+        <el-dialog :visible.sync="dialogVisibleImage" width="10%">
+          <img :src="certificates" style="width: 100%" alt="">
+        </el-dialog>
 
       <div style="margin-top: 20px">
         <span class="font-small">商品信息</span>
@@ -399,6 +415,16 @@
         <el-button type="primary" @click="submitBindCustomerForm">确 定</el-button>
       </div>
     </el-dialog>
+    <el-dialog :title="certificateDialig.title" :visible.sync="certificateDialig.open" append-to-body>
+      <el-form ref="certificateForm" :model="certificateForm" :rules="certificateRules" label-width="100px">
+        <el-form-item label="凭证" prop="certificates">
+          <ImageUpload v-model="photoArr" type="image" :num="10" :width="150" :height="150" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="handleConfirm">确 定</el-button>
+      </div>
+    </el-dialog>
     <el-drawer
       :append-to-body="true"
       size="75%"
@@ -413,20 +439,35 @@
 import {updateUser,getUser } from "@/api/users/user";
 
 import {getCustomerListBySearch } from "@/api/crm/customer";
-
-import {bindCustomer,getExpress, listStoreOrder, getStoreOrder, delStoreOrder, addStoreOrder, updateStoreOrder, exportStoreOrder } from "@/api/store/storeOrder";
+import ImageUpload from '@/components/ImageUpload'
+import {bindCustomer,getExpress, listStoreOrder, getStoreOrder, delStoreOrder, addStoreOrder, updateStoreOrder, exportStoreOrder,uploadCredentials } from "@/api/store/storeOrder";
 import {getAllList} from "@/api/store/city";
 import customerDetails from '../../crm/components/customerDetails.vue';
 export default {
   name: "order",
-  components: {customerDetails },
+  components: {customerDetails, 
+    ImageUpload },
   data() {
     return {
+      dialogVisibleImage: false,
       customerInfo:null,
       customer:{
         title:"客户详情",
         open:false,
       },
+      photoArr:'',
+      certificateDialig:{
+        title:"上传凭证",
+        open:false,
+      },
+      certificateForm:{
+        certificates:null,
+      },
+      certificateRules:{
+        certificates:[
+          { required: true, message: "凭证不能为空", trigger: "change" }
+        ]
+      },
       customers:[],
       bindCustomerDialog:{
         title:"关联客户",
@@ -489,6 +530,7 @@ export default {
       orderTypeOptions:[],
       payTypeOptions:[],
       statusOptions:[],
+      certificates:null,
       order:null,
       user:{},
       logs:[],
@@ -514,6 +556,9 @@ export default {
    
   },
   methods: {
+    showImageDialog() {
+      this.dialogVisible = true;
+    },
     handleCustomer(){
       var that=this;
       this.customer.open = true;
@@ -554,6 +599,21 @@ export default {
         }
       });
     },
+    handleCertificates(){
+      this.certificateDialig.open = true;
+      this.photoArr = '';
+    },
+    handleConfirm(){
+      this.certificateForm.id = this.orderId;
+      this.certificateForm.certificates = this.photoArr;
+      uploadCredentials(this.certificateForm).then(response => {
+              if (response.code === 200) {
+                this.msgSuccess("上传成功");
+                this.certificateDialig.open = false;
+                this.getOrder(this.order.id);
+              }
+            });
+    },
     showExpress(){
       this.expressDialog.open=true;
       getExpress(this.orderId).then(response => {
@@ -692,14 +752,17 @@ export default {
     },
     getOrder(orderId){
         this.orderId=orderId;
+        this.certificates = null;
         getStoreOrder(orderId).then(response => {
             this.order = response.order;
+            if(response.order.certificates != null){
+              this.certificates = response.order.certificates;
+            }  
             this.user = response.user;
             this.logs = response.logs;
             this.items = response.items;
             this.payments=response.payments;
             this.customerInfo=response.customer;
-            
         });
      }
   }

+ 6 - 0
src/views/store/storeOrder/list.vue

@@ -54,6 +54,12 @@
                 :value="item.dictValue"
               />
         </el-select>
+      </el-form-item>
+      <el-form-item label="上传凭证" prop="isUpload">
+         <el-select   v-model="queryParams.isUpload" placeholder="请选择" clearable size="small" >
+          <el-option key="0"  label="未上传" value="0" />
+             <el-option key="1"  label="已上传" value="1" />
+        </el-select>
       </el-form-item>
           <el-form-item label="手机号" prop="userPhone">
             <el-input

+ 6 - 0
src/views/store/storeOrder/myList.vue

@@ -51,6 +51,12 @@
               />
         </el-select>
       </el-form-item>
+      <el-form-item label="上传凭证" prop="isUpload">
+         <el-select   v-model="queryParams.isUpload" placeholder="请选择" clearable size="small" >
+          <el-option key="0"  label="未上传" value="0" />
+             <el-option key="1"  label="已上传" value="1" />
+        </el-select>
+      </el-form-item>
       <el-form-item label="物流状态" prop="deliveryStatus">
          <el-select style="width:220px" v-model="queryParams.deliveryStatus" placeholder="请选择物流状态" clearable size="small" >
          <el-option