Explorar o código

0.0.21

完成用户管理功能的开发
Sean hai 5 meses
pai
achega
cbbc5bc604

+ 13 - 0
src/utils/public.js

@@ -0,0 +1,13 @@
+//1.格式化时间
+export function formatLocalDate(date) {
+  const birthday = new Date(date); // 创建 Date 对象
+  const year = birthday.getFullYear();
+  const month = String(birthday.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,所以加 1
+  const day = String(birthday.getDate()).padStart(2, '0');
+  const hours = String(birthday.getHours()).padStart(2, '0');
+  const minutes = String(birthday.getMinutes()).padStart(2, '0');
+  const seconds = String(birthday.getSeconds()).padStart(2, '0');
+
+  // 返回格式化后的字符串
+  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
+}

+ 2 - 2
src/utils/request.js

@@ -7,8 +7,8 @@ import URL from '@/utils/baseUrl';
 // create an axios instance
 const service = axios.create({
   //千万不能在这里使用绝对地址,这会导致webpack的devserve不生效
-  //baseURL: URL.testUrl, 
-  baseURL: URL.baseUrl, 
+  baseURL: URL.testUrl, 
+  //baseURL: URL.baseUrl, 
   //baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
   //withCredentials: true, // send cookies when cross-domain requests
   timeout: 5000 // request timeout

+ 106 - 0
src/views/role/components/CityCascader.vue

@@ -0,0 +1,106 @@
+<template>
+  <el-cascader
+    :key="cascaderKey"
+    v-model="internalValue"
+    placeholder="选择您要绑定的城市"
+    :props="SearchCityData"
+    filterable
+    clearable
+    @change="handleChange">
+  </el-cascader>
+</template>
+
+<script>
+export default {
+  props: {
+    value: { // 接收外部传递的 v-model 值
+      type: [Array, String], // 允许传入数组或字符串类型的数据
+      default: () => [],
+    },
+  },
+  data() {
+    let self = this;
+    return {
+      internalValue: [], // 用于与级联选择器进行双向绑定的内部数据
+      cascaderKey: 0, // 用于强制刷新 cascader
+      SearchCityData: {
+        checkStrictly: true,
+        lazy: true,
+        async lazyLoad(node, resolve) {
+          const { level, data } = node;
+          let parentId = level == 0 ? 0 : data.value;
+          let parames = {
+            pid: parentId,
+          };
+          self.$store
+            .dispatch("pool/getcityList", parames)
+            .then((res) => {
+              if (res.data) {
+                const nodes = res.data.map((item) => ({
+                  value: item.id,
+                  label: item.name,
+                  leaf: level >= 3,
+                  children: [],
+                }));
+                resolve(nodes);
+              }
+            })
+            .catch(() => {
+              this.$message({
+                type: "info",
+                message: "网络错误,请重试!",
+              });
+            });
+        },
+      },
+    };
+  },
+  watch: {
+    value: {
+      immediate: true, // 组件挂载时立即执行
+      handler(newVal) {
+        try {
+          const parsedValue = Array.isArray(newVal) ? newVal : JSON.parse(newVal);
+          this.internalValue = parsedValue; // 设置内部值
+          if (parsedValue.length) {
+            this.loadCascaderPath(parsedValue); // 动态加载回显的路径
+          }
+        } catch (error) {
+          console.error("无法解析传入的值:", error);
+          this.internalValue = []; // 如果解析失败,重置为默认空数组
+        }
+      },
+    },
+  },
+  methods: {
+    handleChange(value) {
+      // 当选择变化时,向父组件发送更新的值
+      this.$emit("input", value); // v-model 双向绑定
+      this.$emit("update-city-id", value); // 额外事件,方便父组件监听
+    },
+    async loadCascaderPath(path) {
+      for (let i = 0; i < path.length; i++) {
+        const parentId = path[i - 1] || 0; // 获取当前层级的父级ID
+        const level = i; // 当前层级的索引
+        await this.$store.dispatch('pool/getcityList', { pid: parentId })
+          .then((res) => {
+            const nodes = res.data.map(item => ({
+              value: item.id,
+              label: item.name,
+              leaf: level >= 3, // 假设4层结构,设置叶子节点标记
+            }));
+            // 级联选择器加载数据
+            if (level === path.length - 1) {
+              this.internalValue = path; // 确保最后一级路径正确设置
+              this.cascaderKey += 1; // 强制刷新 cascader
+            }
+          });
+      }
+    },
+  },
+};
+</script>
+
+<style scoped>
+/* 可根据需要自定义样式 */
+</style>

+ 3 - 14
src/views/role/components/userAdmin.vue

@@ -17,7 +17,7 @@
             </div>
           </el-form-item>
           <!--选择角色 end------------------------------------------>
-          <el-form-item label="登录账号" :label-width="formLabelWidth" prop="user_name" class="custom-align-right">
+          <el-form-item label="登录账号" :label-width="formLabelWidth" prop="user_name" class="custom-align-right">
             <el-input v-model="form.user_name" autocomplete="off" placeholder="请输入登录账号.."></el-input>
           </el-form-item>
           <div v-if="editId==''">
@@ -77,7 +77,7 @@
     </div>  
 
     <div class="bottomBtnBox">
-      <el-button type="info" @click="clearData">重置</el-button>
+      <el-button type="info" @click="goList">返回</el-button>
       <el-button type="primary" @click="addData" v-if="editId==''">提交</el-button>
       <el-button type="primary" @click="editData" v-else>修改</el-button>
     </div>
@@ -171,18 +171,7 @@ export default {
     },
     //重置表单
     clearData(){
-      this.form.type_id = 10000;
-      this.form.user_name = "";
-      this.form.role_id = "";
-      this.form.password = "";
-      this.form.confirm_password = "";
-      this.form.real_name = "";
-      this.form.mobile = "";
-      this.role_idArr = [];
-      this.capsTooltip1 = false;
-      this.capsTooltip2 = false;
-      this.passwordType1 = 'password';
-      this.passwordType2 = 'password';
+      
     },
     //表单收集 end ------------------------------------------------------------>
     //2.提交表单 start ------------------------------------------------------------>

+ 594 - 5
src/views/role/components/userDefault.vue

@@ -1,23 +1,612 @@
 <template>
-  <div>
-    个人会员
+  <div class="mainBox">
+    <div class="layerBox">
+      <el-form ref="form" :model="form" :rules="loginRules" class="login-form" autocomplete="on" label-position="left" label-width="120px">
+        <div class="formDiv">
+          <!--选择角色 start------------------------------------------>
+          <el-form-item label="所属角色:" :label-width="formLabelWidth" prop="role_id" class="custom-align-right">
+            <div class="formLabelFloatBox">
+              <el-select v-model="form.role_id" placeholder="请选择..">
+                <el-option
+                  v-for="item in role_idArr"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value">
+                </el-option>
+              </el-select>
+            </div>
+          </el-form-item>
+          <!--选择角色 end------------------------------------------>
+          <el-form-item label="登录账号:" :label-width="formLabelWidth" prop="user_name" class="custom-align-right">
+            <el-input v-model="form.user_name" autocomplete="off" placeholder="请输入登录账号.."></el-input>
+          </el-form-item>
+          <div v-if="editId==''">
+            <!--新密码 start------------------------------------------>
+            <div class="PasswordBox">
+              <el-form-item prop="password" label="登录密码:"  class="custom-align-right">
+                <div class="PasswordBody">
+                  <el-input
+                    :key="passwordType1"
+                    ref="password1"
+                    v-model="form.password"
+                    :type="passwordType1"
+                    placeholder="请输入密码"
+                    name="password"
+                    tabindex="2"
+                    autocomplete="off"
+                    @blur="capsTooltip2 = false"
+                  />
+                  <span class="show-pwd" @click="showPwd(1)">
+                    <svg-icon :icon-class="passwordType1 === 'password' ? 'eye' : 'eye-open'" />
+                  </span>
+                </div>
+              </el-form-item>
+            </div>
+            <!--新密码 end------------------------------------------>
+            <!--新密码 start------------------------------------------>
+            <div class="PasswordBox">
+              <el-form-item prop="confirm_password" label="确认密码:"  class="custom-align-right">
+                <div class="PasswordBody">
+                  <el-input
+                    :key="passwordType2"
+                    ref="password2"
+                    v-model="form.confirm_password"
+                    :type="passwordType2"
+                    placeholder="请输入密码"
+                    name="password"
+                    tabindex="2"
+                    autocomplete="off"
+                    @blur="capsTooltip2 = false"
+                  />
+                  <span class="show-pwd" @click="showPwd(2)">
+                    <svg-icon :icon-class="passwordType2 === 'password' ? 'eye' : 'eye-open'" />
+                  </span>
+                </div>
+              </el-form-item>
+            </div>
+            <!--新密码 end------------------------------------------>
+          </div>
+          <el-form-item label="真实姓名:" :label-width="formLabelWidth" prop="real_name" class="custom-align-right">
+            <el-input v-model="form.real_name" autocomplete="off" placeholder="请输入真实姓名.."></el-input>
+          </el-form-item>
+          <el-form-item label="照片:" :label-width="formLabelWidth" prop="" :class="['custom-form-item']" class="custom-align-right">
+            <div class="uploaderBox">
+              <!--图片上传组件 start ------------------------------------------------------------>
+              <div class="avatar-upload-container" @mouseenter="hovering = true" @mouseleave="hovering = false">
+                <!-- 上传组件 -->
+                <el-upload
+                  class="avatar-uploader"
+                  action="#"
+                  :show-file-list="false"
+                  :before-upload="beforeAvatarUpload"
+                >
+                  <!-- 预览图片 -->
+                  <img v-if="photoUrl" :src="photoUrl" class="avatar">
+                  <!-- 上传图标 -->
+                  <div v-else class="chooseImgDiv">
+                    <div>
+                      <img src="@/assets/public/upload/noImage.png">
+                      <div>选择图片</div>
+                    </div>
+                  </div>
+                </el-upload>
+                <!-- 删除按钮,当鼠标悬浮时显示 -->
+                <div v-if="hovering && photoUrl" class="delete-button" @click="handleDelete">
+                  <i class="el-icon-delete"></i>
+                </div>
+              </div>
+              <!--图片上传组件 end ------------------------------------------------------------>
+            </div>
+          </el-form-item>
+          <el-form-item label="身份证号:" :label-width="formLabelWidth" prop="id_card" class="custom-align-right">
+            <el-input v-model="form.id_card" autocomplete="off" placeholder="请输入身份证号.."></el-input>
+          </el-form-item>
+          <el-form-item label="性别:" :label-width="formLabelWidth" prop="gender" class="custom-align-right">
+            <el-radio v-model="form.gender" label="1">男</el-radio>
+            <el-radio v-model="form.gender" label="2">女</el-radio>  
+          </el-form-item>
+          <el-form-item label="手机号:" :label-width="formLabelWidth" prop="mobile" class="custom-align-right">
+            <el-input v-model="form.mobile" autocomplete="off" placeholder="请输入手机号.."></el-input>
+          </el-form-item>
+          <el-form-item label="出生年月:" :label-width="formLabelWidth" prop="birthday" class="custom-align-right">
+            <el-date-picker
+              v-model="form.birthday"
+              type="date"
+              placeholder="选择日期">
+            </el-date-picker>
+          </el-form-item>
+          <el-form-item label="有效期:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-date-picker
+              v-model="timeList"
+              type="daterange"
+              :disabled="form.long_time === 1"
+              range-separator="至"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+              :picker-options="pickerOptions">
+            </el-date-picker>
+            <el-checkbox v-model="form.long_time" :true-label="1" :false-label="0" class="longTimeCheckbox">无限期</el-checkbox>
+          </el-form-item>
+          <el-form-item label="籍贯:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <CityCascader v-model="form.native_place_arr_id" @update-city-id="update_native_place_arr_id"></CityCascader>
+          </el-form-item>
+          <el-form-item label="QQ:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input v-model="form.qq" autocomplete="off" placeholder="请输入QQ号.."></el-input>
+          </el-form-item>
+          <el-form-item label="电子邮箱:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input v-model="form.email" autocomplete="off" placeholder="请输入电子邮箱.."></el-input>
+          </el-form-item>
+          <el-form-item label="邮编:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input v-model="form.zip_code" autocomplete="off" placeholder="请输入邮编.."></el-input>
+          </el-form-item>
+          <el-form-item label="详细地址:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input v-model="form.address" autocomplete="off" placeholder="请输入详细地址.."></el-input>
+          </el-form-item>
+          <el-form-item label="相关资料:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-upload
+              class="upload-demo"
+              :action="uploadFileUrl"
+              :headers="headers"
+              :on-preview="handlePreview"
+              :on-remove="handleRemove"
+              :before-remove="beforeRemove"
+              :on-success="handleUploadSuccess"
+              multiple
+              :limit="30"
+              :on-exceed="handleExceed"
+              :file-list="otherList">
+              <el-button size="small" type="primary">点击上传</el-button>
+              <div slot="tip" class="el-upload__tip">每张图片最大1MB,最多上传30张图片。</div>
+            </el-upload>
+          </el-form-item>
+          <el-form-item label="提示词:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input type="textarea" v-model="form.remark" class="custom-textarea"></el-input>
+          </el-form-item>
+        </div>
+      </el-form>
+    </div>  
+    <div class="bottomBtnBox">
+      <el-button type="info" @click="goList">返回</el-button>
+      <el-button type="primary" @click="addData" v-if="editId==''">提交</el-button>
+      <el-button type="primary" @click="editData" v-else>修改</el-button>
+    </div>
   </div>
 </template>
 
 <script>
+// 引入公用样式
+import '@/styles/global.less';
+// 引入baseUrl
+import URL from '@/utils/baseUrl';
+//城市级联选择器
+import CityCascader from './CityCascader';
+//格式化时间
+import { formatLocalDate } from '@/utils/public';
+
 
 export default {
+  components: {
+    CityCascader, //城市级联选择器
+  },
   data() {
+    // 配置验证规则:用于表单验证
+    const validatePassword = (rule, value, callback) => {
+      if (value.length < 6) {
+        callback(new Error('密码不能低于6位!'))
+      } else {
+        callback()
+      }
+    }
+    const validateEmpty = (rule,value,callback) => {
+      if (!value || value.trim() === "") {
+        callback(new Error('该项不能为空!'));
+      } else {
+        callback();
+      }
+    }
+    const validateArray = (rule,value,callback) => {
+      if (value.length == 0) {
+        callback(new Error('该项不能为空!'))
+      } else {
+        callback()
+      }
+    }
     return {
-      num:1
+      formLabelWidth:"120px",
+      editId:"",
+      uploadFileUrl:URL.testUrl+"/public/uploadFile",//获得上传地址
+      headers: {},
+      form:{
+        type_id:1,//个人会员
+        role_id:"",//角色id 
+        user_name:"",//登录账号
+        password:"",//密码
+        confirm_password:"",//确认密码
+        real_name:"",//真实姓名
+        avatar:"",//照片
+        id_card:"",//身份证号
+        birthday:"",//出生年月
+        gender:"1",//性别
+        mobile:"",//手机号
+        native_place_arr_id:"",//籍贯
+        address:"",//详细地址
+        from_time:"",//有效期开始时间
+        to_time:"",//有效期结束时间
+        long_time:0,//是否为长期 //长期1:长期 0:非长期
+        qq:"",//QQ
+        email:"",//电子邮箱
+        other:[],//相关资料
+        remark:"",//提示词
+      },
+      timeList:[],//时间段
+      otherList:[],//相关资料列表
+      role_idArr:[],//角色id池
+      //上传照片
+      photoUrl:'',
+      hovering: false, // 鼠标悬浮状态 悬浮时显示删除
+      //密码验证
+      capsTooltip1: false,
+      capsTooltip2: false,
+      passwordType1: 'password',
+      passwordType2: 'password',
+      //配置from表单验证规则
+      loginRules: { 
+        //1.角色id
+        role_id: [{ required: true, trigger: 'blur', validator: validateArray }],
+        //2.登录账号
+        user_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //3.密码和确认密码
+        password: [{ required: true, trigger: 'blur', validator: validatePassword }],
+        confirm_password: [{ required: true, trigger: 'blur', validator: validatePassword }],
+        //5.真实姓名
+        real_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //6.手机号
+        mobile: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //7.身份证号
+        id_card: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //8.性别
+        gender: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //9.手机号
+        mobile: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+      },
+      //时间跨度
+      pickerOptions: {
+        selectableRange: '1900-01-01 to 2100-12-31', // 允许选择的日期范围
+        disabledDate(time) {
+          return time.getTime() < Date.now() - 86400000; // 禁用今天之前的日期
+        },
+      },
     };
   },
   methods: {
-    
+    //1.表单收集 start ------------------------------------------------------------>
+    //1.1切换密码框的显示与隐藏
+    showPwd(num) {
+      const passwordTypeKey = 'passwordType' + num; //动态生成 passwordType 的键
+      const passwordRefKey = 'password' + num; //动态生成 password 的引用
+      // 切换密码类型
+      if (this[passwordTypeKey] === 'password') {
+        this[passwordTypeKey] = ''; //显示密码
+      } else {
+        this[passwordTypeKey] = 'password'; //隐藏密码
+      }
+      // 使用 $nextTick 聚焦到对应的密码输入框
+      this.$nextTick(() => {
+        this.$refs[passwordRefKey].focus(); //聚焦到对应的密码输入框
+      });
+    },
+    //1.2获得角色列表池
+    getRoleList(){
+      let data = {
+        page:1,
+        pageSize:100
+      }
+      this.$store.dispatch('userRole/roleList',data).then(res=>{
+        this.role_idArr = res.data.rows.map(item => ({
+          value: item.id,
+          label: item.role_name 
+        }));
+      }).catch(error=>{
+        this.$message({
+          type: 'warning',
+          message: '网络错误,请重试!'
+        });
+      })
+    },
+    //1.4更新籍贯
+    update_native_place_arr_id(value){
+      console.log("籍贯ID已更新:", value);
+      this.form.native_place_arr_id = value;
+    },
+    //1.5重置表单
+    clearData(){
+     
+    },
+    //表单收集 end ------------------------------------------------------------>
+    //2.提交表单 start ------------------------------------------------------------>
+    //2.1 上传图片操作
+    beforeAvatarUpload(file) {
+      const isJPG = file.type === 'image/jpeg';
+      const isPNG = file.type === 'image/png';
+      const isLt2M = file.size / 1024 / 1024 < 2;
+
+      if (!isJPG && !isPNG) {
+        this.$message.error('上传头像图片只能是 JPG 或 PNG 格式!');
+        return false;
+      }
+      if (!isLt2M) {
+        this.$message.error('上传头像图片大小不能超过 2MB!');
+        return false;
+      }
+
+      const formData = new FormData();
+      formData.append('file', file);
+
+      this.$store.dispatch('pool/uploadFile',formData).then(res=> {
+        this.photoUrl = res.data.imgUrl;//显示缩略图
+        this.form.avatar = res.data.imgUrl;//提供表单地址
+        console.log(res.data.imgUrl)
+      }).catch(() => {
+        this.$message({
+          type: 'warning',
+          message: '网络错误,请重试!'
+        });
+      })
+
+      // 阻止默认的上传行为
+      return false;
+    },
+    //2.2 删除图片
+    handleDelete() {
+      this.photoUrl = ''; // 清空图片 URL
+    },
+    //2.3 多文件上传
+    handleRemove(file, fileList) {
+      console.log(file, fileList);
+    },
+    handlePreview(file) {
+      console.log(file);
+    },
+    handleExceed(files, fileList) {
+      this.$message.warning(`当前限制选择 30 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
+    },
+    beforeRemove(file, fileList) {
+      return this.$confirm(`确定移除 ${ file.name }?`);
+    },
+    //获取token
+    getTokenFromCookie() {
+      const name = "Admin-Token=";
+      const decodedCookie = decodeURIComponent(document.cookie);
+      const cookieArray = decodedCookie.split(';');
+      for (let i = 0; i < cookieArray.length; i++) {
+        let cookie = cookieArray[i].trim();
+        if (cookie.indexOf(name) === 0) {
+          return cookie.substring(name.length, cookie.length); // 返回 token
+        }
+      }
+      return ""; // 如果没有找到 token,返回空字符串
+    },
+    //设置token
+    setHeaders() {
+      this.token = this.getTokenFromCookie(); // 从 cookie 中获取 token
+      this.headers = { token: this.token }; // 设置 headers
+      console.log(this.headers); // 打印 headers
+    },
+    //上传成功以后
+    handleUploadSuccess(response) {
+      this.form.other.push(response.data.imgUrl)
+      console.log('上传成功:', response);
+      console.log(this.form.other);
+    },
+    //提交表单
+    addData(){
+      //1.格式化时间戳
+      this.form.birthday = formatLocalDate(this.form.birthday);
+      if(this.form.long_time==0){
+        this.form.from_time = formatLocalDate(this.timeList[0]);
+        this.form.to_time = formatLocalDate(this.timeList[1]);
+      }else{
+        this.form.from_time = "";
+        this.form.to_time = "";
+      }
+      //2.开始验证
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          //3.验证用户是否已经存在
+          this.$store.dispatch('userMember/verifyUserInfo',{user_name:this.form.user_name}).then(res=>{
+            if(res.code==0){
+              //如果code为0表示用户不存在,提交表单
+              this.$store.dispatch('userMember/createUser',this.form).then(res=>{
+                if(res.code==200){
+                  console.log(res);
+                  this.$message({
+                    type: 'success',
+                    message: '用户添加成功!'
+                  });
+                  this.goList();
+                }else{
+                  this.$message({
+                    type: 'warning',
+                    message: res.message
+                  });
+                }
+              })
+            }else if(res.code==200){
+              //如果code==200 表示用户存在,阻止进一步提交
+              this.$message({
+                type: 'warning',
+                message: '该账号已被注册,请更换其他账号!'
+              });
+            }
+          }).catch(error=>{
+            this.$message({
+              type: 'warning',
+              message: '网络错误,请重试!'
+            });
+          })
+        }
+      })
+    },
+    //提交表单 start ------------------------------------------------------------>
+    //3.编辑表单 start ------------------------------------------------------------>
+    //获得用户信息
+    getUserInfo(){
+      this.$store.dispatch('userMember/getUser',{id:this.editId}).then(res=>{
+        console.log(res);
+        //回显数据
+        this.form.type_id = res.data.type_id;
+        this.form.user_name = res.data.user_name;
+        this.form.role_id = res.data.role_id;
+        this.form.real_name = res.data.real_name;
+        this.form.mobile = res.data.mobile;
+        this.photoUrl = res.data.avatar;
+        this.form.avatar = res.data.avatar;
+        this.form.id_card = res.data.id_card;
+        this.form.birthday = res.data.birthday;
+        //还原有效期
+        if(res.data.long_time==0){
+          this.timeList = [
+            res.data.from_time,
+            res.data.to_time
+          ]
+          this.form.from_time = res.data.from_time;
+          this.form.to_time = res.data.to_time;
+          this.form.long_time = 0;
+        }else{
+          this.form.from_time = "";
+          this.form.to_time = "";
+          this.form.long_time = 1;
+        }
+        this.form.qq = res.data.qq;
+        this.form.email = res.data.email;
+        this.form.address = res.data.address;
+        this.form.zip_code = res.data.zip_code;
+        this.form.remark = res.data.remark;
+        this.form.native_place_arr_id = res.data.native_place_arr_id;
+        // 处理文件列表
+        const fileArrayString = res.data.other; // 假设这是一个字符串格式的数组
+        const fileArray = JSON.parse(fileArrayString); // 解析为数组
+        this.form.other.push(...fileArray); // 将解析出来的值 push 到 this.form.other
+        // 将文件列表赋值给 otherList,生成默认文件名
+        this.otherList = fileArray.map((url, index) => ({
+          name: `文件${index + 1}`, // 生成文件名
+          url: url,                // 文件的 URL
+          status: 'success'        // 设置状态为 success
+        }));
+      }).catch(error=>{
+        this.$message({
+          type: 'warning',
+          message: '网络错误,请重试!'
+        });
+      })
+    },
+    //修改用户
+    editData(){
+      //1.格式化时间戳
+      this.form.birthday = formatLocalDate(this.form.birthday);
+      if(this.form.long_time==0){
+        this.form.from_time = formatLocalDate(this.timeList[0]);
+        this.form.to_time = formatLocalDate(this.timeList[1]);
+      }else{
+        this.form.from_time = "";
+        this.form.to_time = "";
+      }
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          //1.验证用户是否存在
+          this.$store.dispatch('userMember/verifyUserInfo',{id:this.editId,user_name:this.form.user_name}).then(res=>{
+            if(res.code==0){
+              console.log(this.form);
+              this.form.native_place_arr_id = JSON.parse(this.form.native_place_arr_id);
+
+              //2.设置修改的用户id
+              this.form.id = this.editId;
+              //3.提交用户修改
+              //如果code为0表示用户不存在,提交表单
+              this.$store.dispatch('userMember/updateUser',this.form).then(res=>{
+                console.log(res);
+                this.$message({
+                  type: 'success',
+                  message: '用户添加成功!'
+                });
+                this.goList();
+              })
+            }else if(res.code==200){
+              //如果code==200 表示用户存在,阻止进一步提交
+              this.$message({
+                type: 'warning',
+                message: '该账号已被注册,请更换其他账号!'
+              });
+            }
+          }).catch(error=>{
+            this.$message({
+              type: 'warning',
+              message: '网络错误,请重试!'
+            });
+          })
+        }
+      })
+    },
+    //编辑表单 end ------------------------------------------------------------>
+    goList(){
+      this.$router.push({
+        path: '/userList',
+      });
+    },
   },
+  mounted(){
+    this.getRoleList();
+    //判断是新建还是回显
+    if(this.$route.query.id!=undefined){
+      this.editId = this.$route.query.id;
+      console.log("编辑用户!")
+      this.getUserInfo();
+    }else{
+      console.log("添加用户!")
+    }
+    //设置token
+    this.setHeaders(); // 在组件挂载时设置 headers
+  }
 };
 </script>
 
 <style scoped lang="less">
-  
+  .PasswordBox {
+    display: flex;
+    align-items: center;
+    .el-form-item {
+      flex: 1;
+    }
+    .PasswordTitle {
+      width:120px;
+      text-align: right;
+      margin-right: 10px;
+      margin-bottom:22px;
+    }
+    .PasswordBody {
+      flex: 1;
+      display: flex;
+      align-items: center;
+    }
+    .show-pwd {
+      margin-left: 10px;
+    }
+  }
+  .longTimeCheckbox {
+    margin-left: 10px;
+  }
+  //执行v-deep穿透scope选择器 start------------------------------------------------------------>*/
+  ::v-deep .custom-form-item > .el-form-item__label {
+    line-height: 140px !important;
+  }
+  ::v-deep .custom-textarea .el-textarea__inner {
+    resize: none; /* 禁止用户拖拽调整大小 */
+  }
+  ::v-deep .custom-align-right .el-form-item__label {
+    text-align: right; /* 设置标签文字右对齐 */
+  }
+  ::v-deep .el-select {
+    width: 100%; /* 禁止用户拖拽调整大小 */
+  }
+  //执行v-deep穿透scope选择器 end------------------------------------------------------------>*/
 </style>

+ 549 - 5
src/views/role/components/userEnterprise.vue

@@ -1,23 +1,567 @@
 <template>
-  <div>
-    企业会员
+  <div class="mainBox">
+    <div class="layerBox">
+      <el-form ref="form" :model="form" :rules="loginRules" class="login-form" autocomplete="on" label-position="left" label-width="120px">
+        <div class="formDiv">
+          <!--选择角色 start------------------------------------------>
+          <el-form-item label="所属角色:" :label-width="formLabelWidth" prop="role_id" class="custom-align-right">
+            <div class="formLabelFloatBox">
+              <el-select v-model="form.role_id" placeholder="请选择..">
+                <el-option
+                  v-for="item in role_idArr"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value">
+                </el-option>
+              </el-select>
+            </div>
+          </el-form-item>
+          <!--选择角色 end------------------------------------------>
+          <el-form-item label="登录账号:" :label-width="formLabelWidth" prop="user_name" class="custom-align-right">
+            <el-input v-model="form.user_name" autocomplete="off" placeholder="请输入登录账号.."></el-input>
+          </el-form-item>
+          <div v-if="editId==''">
+            <!--新密码 start------------------------------------------>
+            <div class="PasswordBox">
+              <el-form-item prop="password" label="登录密码:"  class="custom-align-right">
+                <div class="PasswordBody">
+                  <el-input
+                    :key="passwordType1"
+                    ref="password1"
+                    v-model="form.password"
+                    :type="passwordType1"
+                    placeholder="请输入密码"
+                    name="password"
+                    tabindex="2"
+                    autocomplete="off"
+                    @blur="capsTooltip2 = false"
+                  />
+                  <span class="show-pwd" @click="showPwd(1)">
+                    <svg-icon :icon-class="passwordType1 === 'password' ? 'eye' : 'eye-open'" />
+                  </span>
+                </div>
+              </el-form-item>
+            </div>
+            <!--新密码 end------------------------------------------>
+            <!--新密码 start------------------------------------------>
+            <div class="PasswordBox">
+              <el-form-item prop="confirm_password" label="确认密码:"  class="custom-align-right">
+                <div class="PasswordBody">
+                  <el-input
+                    :key="passwordType2"
+                    ref="password2"
+                    v-model="form.confirm_password"
+                    :type="passwordType2"
+                    placeholder="请输入密码"
+                    name="password"
+                    tabindex="2"
+                    autocomplete="off"
+                    @blur="capsTooltip2 = false"
+                  />
+                  <span class="show-pwd" @click="showPwd(2)">
+                    <svg-icon :icon-class="passwordType2 === 'password' ? 'eye' : 'eye-open'" />
+                  </span>
+                </div>
+              </el-form-item>
+            </div>
+            <!--新密码 end------------------------------------------>
+          </div>
+          <el-form-item label="企业名称:" :label-width="formLabelWidth" prop="business_name" class="custom-align-right">
+            <el-input v-model="form.business_name" autocomplete="off" placeholder="请输入企业名称.."></el-input>
+          </el-form-item>
+          <el-form-item label="详细地址:" :label-width="formLabelWidth" prop="address_arr_id" class="custom-align-right">
+            <CityCascader v-model="form.address_arr_id" @update-city-id="update_address_arr_id"></CityCascader>
+          </el-form-item>
+          <el-form-item label="负责人:" :label-width="formLabelWidth" prop="real_name" class="custom-align-right">
+            <el-input v-model="form.real_name" autocomplete="off" placeholder="请输入负责人姓名.."></el-input>
+          </el-form-item>
+          <el-form-item label="负责人职务:" :label-width="formLabelWidth" prop="position" class="custom-align-right">
+            <el-input v-model="form.position" autocomplete="off" placeholder="请输入负责人职务.."></el-input>
+          </el-form-item>
+          <el-form-item label="负责人电话:" :label-width="formLabelWidth" prop="mobile" class="custom-align-right">
+            <el-input v-model="form.mobile" autocomplete="off" placeholder="请输入负责人联系电话.."></el-input>
+          </el-form-item>
+          <el-form-item label="负责人身份证:" :label-width="formLabelWidth" prop="id_card" class="custom-align-right">
+            <el-input v-model="form.id_card" autocomplete="off" placeholder="请输入负责人身份证号.."></el-input>
+          </el-form-item>
+          <el-form-item label="法人:" :label-width="formLabelWidth" prop="legal_person_real_name" class="custom-align-right">
+            <el-input v-model="form.legal_person_real_name" autocomplete="off" placeholder="请输入法人姓名.."></el-input>
+          </el-form-item>
+          <el-form-item label="法人电话:" :label-width="formLabelWidth" prop="legal_person_mobile" class="custom-align-right">
+            <el-input v-model="form.legal_person_mobile" autocomplete="off" placeholder="请输入法人联系电话.."></el-input>
+          </el-form-item>
+          <el-form-item label="法人身份证:" :label-width="formLabelWidth" prop="legal_person_id_card" class="custom-align-right">
+            <el-input v-model="form.legal_person_id_card" autocomplete="off" placeholder="请输入法人身份证号.."></el-input>
+          </el-form-item>
+          <el-form-item label="有效期:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-date-picker
+              v-model="timeList"
+              type="daterange"
+              :disabled="form.long_time === 1"
+              range-separator="至"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+              :picker-options="pickerOptions">
+            </el-date-picker>
+            <el-checkbox v-model="form.long_time" :true-label="1" :false-label="0" class="longTimeCheckbox">无限期</el-checkbox>
+          </el-form-item>
+          <el-form-item label="传真:" :label-width="formLabelWidth" prop="fax" class="custom-align-right">
+            <el-input v-model="form.fax" autocomplete="off" placeholder="请输入传真号码.."></el-input>
+          </el-form-item>
+          <el-form-item label="邮编:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input v-model="form.zip_code" autocomplete="off" placeholder="请输入邮编.."></el-input>
+          </el-form-item>
+          <el-form-item label="QQ:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input v-model="form.qq" autocomplete="off" placeholder="请输入QQ号.."></el-input>
+          </el-form-item>
+          <el-form-item label="电子邮箱:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input v-model="form.email" autocomplete="off" placeholder="请输入电子邮箱.."></el-input>
+          </el-form-item>
+          <el-form-item label="相关资料:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-upload
+              class="upload-demo"
+              :action="uploadFileUrl"
+              :headers="headers"
+              :on-preview="handlePreview"
+              :on-remove="handleRemove"
+              :before-remove="beforeRemove"
+              :on-success="handleUploadSuccess"
+              multiple
+              :limit="30"
+              :on-exceed="handleExceed"
+              :file-list="otherList">
+              <el-button size="small" type="primary">点击上传</el-button>
+              <div slot="tip" class="el-upload__tip">每张图片最大1MB,最多上传30张图片。</div>
+            </el-upload>
+          </el-form-item>
+          <el-form-item label="提示词:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input type="textarea" v-model="form.remark" class="custom-textarea"></el-input>
+          </el-form-item>
+        </div>
+      </el-form>
+    </div>  
+    <div class="bottomBtnBox">
+      <el-button type="info" @click="goList">返回</el-button>
+      <el-button type="primary" @click="addData" v-if="editId==''">提交</el-button>
+      <el-button type="primary" @click="editData" v-else>修改</el-button>
+    </div>
   </div>
 </template>
 
 <script>
+// 引入公用样式
+import '@/styles/global.less';
+// 引入baseUrl
+import URL from '@/utils/baseUrl';
+//城市级联选择器
+import CityCascader from './CityCascader';
+//格式化时间
+import { formatLocalDate } from '@/utils/public';
+
 
 export default {
+  components: {
+    CityCascader, //城市级联选择器
+  },
   data() {
+    // 配置验证规则:用于表单验证
+    const validatePassword = (rule, value, callback) => {
+      if (value.length < 6) {
+        callback(new Error('密码不能低于6位!'))
+      } else {
+        callback()
+      }
+    }
+    const validateEmpty = (rule,value,callback) => {
+      if (!value || value.trim() === "") {
+        callback(new Error('该项不能为空!'));
+      } else {
+        callback();
+      }
+    }
+    const validateArray = (rule,value,callback) => {
+      if (value.length == 0) {
+        callback(new Error('该项不能为空!'))
+      } else {
+        callback()
+      }
+    }
     return {
-      num:1
+      formLabelWidth:"120px",
+      editId:"",
+      uploadFileUrl:URL.testUrl+"/public/uploadFile",//获得上传地址
+      headers: {},
+      form:{
+        type_id:3,//企业会员
+        role_id:"",//角色id 
+        user_name:"",//登录账号
+        password:"",//密码
+        confirm_password:"",//确认密码
+        real_name:"",//真实姓名
+        id_card:"",//身份证号
+        mobile:"",//手机号
+        address_arr_id:"",//工作区域
+        from_time:"",//有效期开始时间
+        to_time:"",//有效期结束时间
+        long_time:0,//是否为长期 //长期1:长期 0:非长期
+        qq:"",//QQ
+        email:"",//电子邮箱
+        other:[],//相关资料
+        remark:"",//提示词
+        //企业相关字段
+        fax:"",//传真
+        business_name:"",//企业名称
+        position:"",//负责人职务
+        legal_person_real_name:"",//法人姓名
+        legal_person_mobile:"",//法人手机号
+        legal_person_id_card:"",//法人身份证号
+      },
+      timeList:[],//时间段
+      otherList:[],//相关资料列表
+      role_idArr:[],//角色id池
+      //密码验证
+      capsTooltip1: false,
+      capsTooltip2: false,
+      passwordType1: 'password',
+      passwordType2: 'password',
+      //配置from表单验证规则
+      loginRules: { 
+        //1.角色id
+        role_id: [{ required: true, trigger: 'blur', validator: validateArray }],
+        //2.登录账号
+        user_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //3.密码和确认密码
+        password: [{ required: true, trigger: 'blur', validator: validatePassword }],
+        confirm_password: [{ required: true, trigger: 'blur', validator: validatePassword }],
+        //4.调研员编号
+        number: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //5.真实姓名
+        real_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //6.手机号
+        mobile: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //7.身份证号
+        id_card: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //8.性别
+        gender: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //9.手机号
+        mobile: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //10.工作区域
+        address_arr_id: [{ required: true, trigger: 'blur', validator: validateArray }],
+        //11.企业名称
+        business_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //12.负责人职务
+        position: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //12.法人姓名
+        legal_person_real_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //13.法人电话
+        legal_person_mobile: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //14.法人身份证号
+        legal_person_id_card: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+      },
+      //时间跨度
+      pickerOptions: {
+        selectableRange: '1900-01-01 to 2100-12-31', // 允许选择的日期范围
+        disabledDate(time) {
+          return time.getTime() < Date.now() - 86400000; // 禁用今天之前的日期
+        },
+      },
     };
   },
   methods: {
-    
+    //1.表单收集 start ------------------------------------------------------------>
+    //1.1切换密码框的显示与隐藏
+    showPwd(num) {
+      const passwordTypeKey = 'passwordType' + num; //动态生成 passwordType 的键
+      const passwordRefKey = 'password' + num; //动态生成 password 的引用
+      // 切换密码类型
+      if (this[passwordTypeKey] === 'password') {
+        this[passwordTypeKey] = ''; //显示密码
+      } else {
+        this[passwordTypeKey] = 'password'; //隐藏密码
+      }
+      // 使用 $nextTick 聚焦到对应的密码输入框
+      this.$nextTick(() => {
+        this.$refs[passwordRefKey].focus(); //聚焦到对应的密码输入框
+      });
+    },
+    //1.2获得角色列表池
+    getRoleList(){
+      let data = {
+        page:1,
+        pageSize:100
+      }
+      this.$store.dispatch('userRole/roleList',data).then(res=>{
+        this.role_idArr = res.data.rows.map(item => ({
+          value: item.id,
+          label: item.role_name 
+        }));
+      }).catch(error=>{
+        this.$message({
+          type: 'warning',
+          message: '网络错误,请重试!'
+        });
+      })
+    },
+    //1.3更新工作区域
+    update_address_arr_id(value){
+      console.log("工作区域ID已更新:", value);
+      this.form.address_arr_id = value;
+    },
+    //1.5重置表单
+    clearData(){
+      
+    },
+    //表单收集 end ------------------------------------------------------------>
+    //2.提交表单 start ------------------------------------------------------------>
+    //2.3 多文件上传
+    handleRemove(file, fileList) {
+      console.log(file, fileList);
+    },
+    handlePreview(file) {
+      console.log(file);
+    },
+    handleExceed(files, fileList) {
+      this.$message.warning(`当前限制选择 30 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
+    },
+    beforeRemove(file, fileList) {
+      return this.$confirm(`确定移除 ${ file.name }?`);
+    },
+    //获取token
+    getTokenFromCookie() {
+      const name = "Admin-Token=";
+      const decodedCookie = decodeURIComponent(document.cookie);
+      const cookieArray = decodedCookie.split(';');
+      for (let i = 0; i < cookieArray.length; i++) {
+        let cookie = cookieArray[i].trim();
+        if (cookie.indexOf(name) === 0) {
+          return cookie.substring(name.length, cookie.length); // 返回 token
+        }
+      }
+      return ""; // 如果没有找到 token,返回空字符串
+    },
+    //设置token
+    setHeaders() {
+      this.token = this.getTokenFromCookie(); // 从 cookie 中获取 token
+      this.headers = { token: this.token }; // 设置 headers
+      console.log(this.headers); // 打印 headers
+    },
+    //上传成功以后
+    handleUploadSuccess(response) {
+      this.form.other.push(response.data.imgUrl)
+      console.log('上传成功:', response);
+      console.log(this.form.other);
+    },
+    //提交表单
+    addData(){
+      //1.格式化时间戳
+      if(this.form.long_time==0){
+        this.form.from_time = formatLocalDate(this.timeList[0]);
+        this.form.to_time = formatLocalDate(this.timeList[1]);
+      }else{
+        this.form.from_time = "";
+        this.form.to_time = "";
+      }
+      //2.开始验证
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          //3.验证用户是否已经存在
+          this.$store.dispatch('userMember/verifyUserInfo',{user_name:this.form.user_name}).then(res=>{
+            if(res.code==0){
+              //如果code为0表示用户不存在,提交表单
+              this.$store.dispatch('userMember/createUser',this.form).then(res=>{
+                if(res.code==200){
+                  console.log(res);
+                  this.$message({
+                    type: 'success',
+                    message: '用户添加成功!'
+                  });
+                  this.goList();
+                }else{
+                  this.$message({
+                    type: 'warning',
+                    message: res.message
+                  });
+                }
+              })
+            }else if(res.code==200){
+              //如果code==200 表示用户存在,阻止进一步提交
+              this.$message({
+                type: 'warning',
+                message: '该账号已被注册,请更换其他账号!'
+              });
+            }
+          }).catch(error=>{
+            this.$message({
+              type: 'warning',
+              message: '网络错误,请重试!'
+            });
+          })
+        }
+      })
+    },
+    //提交表单 start ------------------------------------------------------------>
+    //3.编辑表单 start ------------------------------------------------------------>
+    //获得用户信息
+    getUserInfo(){
+      this.$store.dispatch('userMember/getUser',{id:this.editId}).then(res=>{
+        console.log(res);
+        //回显数据
+        this.form.type_id = res.data.type_id;
+        this.form.user_name = res.data.user_name;
+        this.form.role_id = res.data.role_id;
+        this.form.real_name = res.data.real_name;
+        this.form.mobile = res.data.mobile;
+        this.form.number = res.data.number;
+        this.form.avatar = res.data.avatar;
+        this.form.id_card = res.data.id_card;
+        this.form.fax = res.data.fax;
+        this.form.business_name = res.data.business_name;
+        this.form.legal_person_id_card = res.data.legal_person_id_card;
+        this.form.legal_person_mobile = res.data.legal_person_mobile;
+        this.form.legal_person_real_name = res.data.legal_person_real_name;
+        this.form.position = res.data.position;
+        //还原有效期
+        if(res.data.long_time==0){
+          this.timeList = [
+            res.data.from_time,
+            res.data.to_time
+          ]
+          this.form.from_time = res.data.from_time;
+          this.form.to_time = res.data.to_time;
+          this.form.long_time = 0;
+        }else{
+          this.form.from_time = "";
+          this.form.to_time = "";
+          this.form.long_time = 1;
+        }
+        this.form.qq = res.data.qq;
+        this.form.email = res.data.email;
+        this.form.zip_code = res.data.zip_code;
+        this.form.remark = res.data.remark;
+        this.form.address_arr_id = res.data.address_arr_id;
+        
+        // 处理文件列表
+        const fileArrayString = res.data.other; // 假设这是一个字符串格式的数组
+        const fileArray = JSON.parse(fileArrayString); // 解析为数组
+        this.form.other.push(...fileArray); // 将解析出来的值 push 到 this.form.other
+        // 将文件列表赋值给 otherList,生成默认文件名
+        this.otherList = fileArray.map((url, index) => ({
+          name: `文件${index + 1}`, // 生成文件名
+          url: url,                // 文件的 URL
+          status: 'success'        // 设置状态为 success
+        }));
+      }).catch(error=>{
+        this.$message({
+          type: 'warning',
+          message: '网络错误,请重试!'
+        });
+      })
+    },
+    //修改用户
+    editData(){
+      //1.格式化时间戳
+      if(this.form.long_time==0){
+        this.form.from_time = formatLocalDate(this.timeList[0]);
+        this.form.to_time = formatLocalDate(this.timeList[1]);
+      }else{
+        this.form.from_time = "";
+        this.form.to_time = "";
+      }
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          //1.验证用户是否存在
+          this.$store.dispatch('userMember/verifyUserInfo',{id:this.editId,user_name:this.form.user_name}).then(res=>{
+            if(res.code==0){
+              console.log(this.form);
+              this.form.address_arr_id = JSON.parse(this.form.address_arr_id);
+              //2.设置修改的用户id
+              this.form.id = this.editId;
+              //3.提交用户修改
+              //如果code为0表示用户不存在,提交表单
+              this.$store.dispatch('userMember/updateUser',this.form).then(res=>{
+                console.log(res);
+                this.$message({
+                  type: 'success',
+                  message: '用户添加成功!'
+                });
+                this.goList();
+              })
+            }else if(res.code==200){
+              //如果code==200 表示用户存在,阻止进一步提交
+              this.$message({
+                type: 'warning',
+                message: '该账号已被注册,请更换其他账号!'
+              });
+            }
+          }).catch(error=>{
+            this.$message({
+              type: 'warning',
+              message: '网络错误,请重试!'
+            });
+          })
+        }
+      })
+    },
+    //编辑表单 end ------------------------------------------------------------>
+    goList(){
+      this.$router.push({
+        path: '/userList',
+      });
+    },
   },
+  mounted(){
+    this.getRoleList();
+    //判断是新建还是回显
+    if(this.$route.query.id!=undefined){
+      this.editId = this.$route.query.id;
+      console.log("编辑用户!")
+      this.getUserInfo();
+    }else{
+      console.log("添加用户!")
+    }
+    //设置token
+    this.setHeaders(); // 在组件挂载时设置 headers
+  }
 };
 </script>
 
 <style scoped lang="less">
-  
+  .PasswordBox {
+    display: flex;
+    align-items: center;
+    .el-form-item {
+      flex: 1;
+    }
+    .PasswordTitle {
+      width:120px;
+      text-align: right;
+      margin-right: 10px;
+      margin-bottom:22px;
+    }
+    .PasswordBody {
+      flex: 1;
+      display: flex;
+      align-items: center;
+    }
+    .show-pwd {
+      margin-left: 10px;
+    }
+  }
+  .longTimeCheckbox {
+    margin-left: 10px;
+  }
+  //执行v-deep穿透scope选择器 start------------------------------------------------------------>*/
+  ::v-deep .custom-form-item > .el-form-item__label {
+    line-height: 140px !important;
+  }
+  ::v-deep .custom-textarea .el-textarea__inner {
+    resize: none; /* 禁止用户拖拽调整大小 */
+  }
+  ::v-deep .custom-align-right .el-form-item__label {
+    text-align: right; /* 设置标签文字右对齐 */
+  }
+  ::v-deep .el-select {
+    width: 100%; /* 禁止用户拖拽调整大小 */
+  }
+  //执行v-deep穿透scope选择器 end------------------------------------------------------------>*/
 </style>

+ 194 - 84
src/views/role/components/userInvestigate.vue

@@ -17,7 +17,7 @@
             </div>
           </el-form-item>
           <!--选择角色 end------------------------------------------>
-          <el-form-item label="登录账号" :label-width="formLabelWidth" prop="user_name" class="custom-align-right">
+          <el-form-item label="登录账号" :label-width="formLabelWidth" prop="user_name" class="custom-align-right">
             <el-input v-model="form.user_name" autocomplete="off" placeholder="请输入登录账号.."></el-input>
           </el-form-item>
           <div v-if="editId==''">
@@ -72,7 +72,7 @@
           <el-form-item label="真实姓名:" :label-width="formLabelWidth" prop="real_name" class="custom-align-right">
             <el-input v-model="form.real_name" autocomplete="off" placeholder="请输入真实姓名.."></el-input>
           </el-form-item>
-          <el-form-item label="照片:" :label-width="formLabelWidth" prop="user_photo" :class="['custom-form-item']" class="custom-align-right">
+          <el-form-item label="照片:" :label-width="formLabelWidth" prop="" :class="['custom-form-item']" class="custom-align-right">
             <div class="uploaderBox">
               <!--图片上传组件 start ------------------------------------------------------------>
               <div class="avatar-upload-container" @mouseenter="hovering = true" @mouseleave="hovering = false">
@@ -118,22 +118,24 @@
           <el-form-item label="手机号:" :label-width="formLabelWidth" prop="mobile" class="custom-align-right">
             <el-input v-model="form.mobile" autocomplete="off" placeholder="请输入手机号.."></el-input>
           </el-form-item>
-          <el-form-item label="工作区域:" :label-width="formLabelWidth" prop="city_arr_id" class="custom-align-right">
+          <el-form-item label="工作区域:" :label-width="formLabelWidth" prop="address_arr_id" class="custom-align-right">
             <!-- 级联选择器 -->
+            <CityCascader v-model="form.address_arr_id" @update-city-id="update_address_arr_id"></CityCascader>
           </el-form-item>
-          <el-form-item label="有效期:" :label-width="formLabelWidth" prop="mobile" class="custom-align-right">
+          <el-form-item label="有效期:" :label-width="formLabelWidth" prop="" class="custom-align-right">
             <el-date-picker
-              v-model="form.city_arr_id"
+              v-model="timeList"
               type="daterange"
               :disabled="form.long_time === 1"
               range-separator="至"
               start-placeholder="开始日期"
-              end-placeholder="结束日期">
+              end-placeholder="结束日期"
+              :picker-options="pickerOptions">
             </el-date-picker>
             <el-checkbox v-model="form.long_time" :true-label="1" :false-label="0" class="longTimeCheckbox">无限期</el-checkbox>
           </el-form-item>
           <el-form-item label="籍贯:" :label-width="formLabelWidth" prop="" class="custom-align-right">
-            <!-- 级联选择器 -->
+            <CityCascader v-model="form.native_place_arr_id" @update-city-id="update_native_place_arr_id"></CityCascader>
           </el-form-item>
           <el-form-item label="QQ:" :label-width="formLabelWidth" prop="" class="custom-align-right">
             <el-input v-model="form.qq" autocomplete="off" placeholder="请输入QQ号.."></el-input>
@@ -145,20 +147,21 @@
             <el-input v-model="form.zip_code" autocomplete="off" placeholder="请输入邮编.."></el-input>
           </el-form-item>
           <el-form-item label="详细地址:" :label-width="formLabelWidth" prop="" class="custom-align-right">
-            <!-- 级联选择器 -->
+            <el-input v-model="form.address" autocomplete="off" placeholder="请输入详细地址.."></el-input>
           </el-form-item>
           <el-form-item label="相关资料:" :label-width="formLabelWidth" prop="" class="custom-align-right">
-            <!-- <el-input v-model="form.other" autocomplete="off" placeholder=""></el-input> -->
             <el-upload
               class="upload-demo"
               :action="uploadFileUrl"
+              :headers="headers"
               :on-preview="handlePreview"
               :on-remove="handleRemove"
               :before-remove="beforeRemove"
+              :on-success="handleUploadSuccess"
               multiple
               :limit="30"
               :on-exceed="handleExceed"
-              :file-list="form.other">
+              :file-list="otherList">
               <el-button size="small" type="primary">点击上传</el-button>
               <div slot="tip" class="el-upload__tip">每张图片最大1MB,最多上传30张图片。</div>
             </el-upload>
@@ -170,7 +173,7 @@
       </el-form>
     </div>  
     <div class="bottomBtnBox">
-      <el-button type="info" @click="clearData">重置</el-button>
+      <el-button type="info" @click="goList">返回</el-button>
       <el-button type="primary" @click="addData" v-if="editId==''">提交</el-button>
       <el-button type="primary" @click="editData" v-else>修改</el-button>
     </div>
@@ -180,10 +183,17 @@
 <script>
 // 引入公用样式
 import '@/styles/global.less';
-// 引入
+// 引入baseUrl
 import URL from '@/utils/baseUrl';
+//城市级联选择器
+import CityCascader from './CityCascader';
+//格式化时间
+import { formatLocalDate } from '@/utils/public';
 
 export default {
+  components: {
+    CityCascader, //城市级联选择器
+  },
   data() {
     // 配置验证规则:用于表单验证
     const validatePassword = (rule, value, callback) => {
@@ -211,29 +221,33 @@ export default {
       formLabelWidth:"120px",
       editId:"",
       uploadFileUrl:URL.testUrl+"/public/uploadFile",//获得上传地址
+      headers: {},
       form:{
-        type_id:10000,//10000管理
+        type_id:4,//调研
         role_id:"",//角色id 
         user_name:"",//登录账号
         password:"",//密码
         confirm_password:"",//确认密码
         number:"",//调研员编号
         real_name:"",//真实姓名
-        user_photo:"",//照片
+        avatar:"",//照片
         id_card:"",//身份证号
         birthday:"",//出生年月
         gender:"1",//性别
         mobile:"",//手机号
-        city_arr_id:"",//工作区域
+        native_place_arr_id:"",//籍贯
+        address_arr_id:"",//工作区域
+        address:"",//详细地址
         from_time:"",//有效期开始时间
         to_time:"",//有效期结束时间
         long_time:0,//是否为长期 //长期1:长期 0:非长期
-        native_place_arr_id:"",//籍贯
         qq:"",//QQ
         email:"",//电子邮箱
         other:[],//相关资料
         remark:"",//提示词
       },
+      timeList:[],//时间段
+      otherList:[],//相关资料列表
       role_idArr:[],//角色id池
       //上传照片
       photoUrl:'',
@@ -246,7 +260,7 @@ export default {
       //配置from表单验证规则
       loginRules: { 
         //1.角色id
-        role_id: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        role_id: [{ required: true, trigger: 'blur', validator: validateArray }],
         //2.登录账号
         user_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
         //3.密码和确认密码
@@ -265,16 +279,20 @@ export default {
         //9.手机号
         mobile: [{ required: true, trigger: 'blur', validator: validateEmpty }],
         //10.工作区域
-        city_arr_id: [{ required: true, trigger: 'blur', validator: validateArray }],
-        //11.有效期
-        long_time: [{ required: true, trigger: 'blur', validator: validateEmpty }],
-        
-      }
+        address_arr_id: [{ required: true, trigger: 'blur', validator: validateArray }],
+      },
+      //时间跨度
+      pickerOptions: {
+        selectableRange: '1900-01-01 to 2100-12-31', // 允许选择的日期范围
+        disabledDate(time) {
+          return time.getTime() < Date.now() - 86400000; // 禁用今天之前的日期
+        },
+      },
     };
   },
   methods: {
     //1.表单收集 start ------------------------------------------------------------>
-    // 切换密码框的显示与隐藏
+    //1.1切换密码框的显示与隐藏
     showPwd(num) {
       const passwordTypeKey = 'passwordType' + num; //动态生成 passwordType 的键
       const passwordRefKey = 'password' + num; //动态生成 password 的引用
@@ -289,7 +307,7 @@ export default {
         this.$refs[passwordRefKey].focus(); //聚焦到对应的密码输入框
       });
     },
-    //获得角色列表池
+    //1.2获得角色列表池
     getRoleList(){
       let data = {
         page:1,
@@ -302,25 +320,24 @@ export default {
         }));
       }).catch(error=>{
         this.$message({
-          type: 'info',
+          type: 'warning',
           message: '网络错误,请重试!'
         });
       })
     },
-    //重置表单
+    //1.3更新工作区域
+    update_address_arr_id(value){
+      console.log("工作区域ID已更新:", value);
+      this.form.City_arr_id = value;
+    },
+    //1.4更新籍贯
+    update_native_place_arr_id(value){
+      console.log("籍贯ID已更新:", value);
+      this.form.native_place_arr_id = value;
+    },
+    //1.5重置表单
     clearData(){
-      this.form.type_id = 10000;
-      this.form.user_name = "";
-      this.form.role_id = "";
-      this.form.password = "";
-      this.form.confirm_password = "";
-      this.form.real_name = "";
-      this.form.mobile = "";
-      this.role_idArr = [];
-      this.capsTooltip1 = false;
-      this.capsTooltip2 = false;
-      this.passwordType1 = 'password';
-      this.passwordType2 = 'password';
+     
     },
     //表单收集 end ------------------------------------------------------------>
     //2.提交表单 start ------------------------------------------------------------>
@@ -331,7 +348,7 @@ export default {
       const isLt2M = file.size / 1024 / 1024 < 2;
 
       if (!isJPG && !isPNG) {
-        this.$message.error('上传头像图片只能是 JPG 或 PNG 格!');
+        this.$message.error('上传头像图片只能是 JPG 或 PNG 格��!');
         return false;
       }
       if (!isLt2M) {
@@ -344,11 +361,11 @@ export default {
 
       this.$store.dispatch('pool/uploadFile',formData).then(res=> {
         this.photoUrl = res.data.imgUrl;//显示缩略图
-        this.form.logo = res.data.imgUrl;//提供表单地址
+        this.form.avatar = res.data.imgUrl;//提供表单地址
         console.log(res.data.imgUrl)
       }).catch(() => {
         this.$message({
-          type: 'info',
+          type: 'warning',
           message: '网络错误,请重试!'
         });
       })
@@ -373,33 +390,78 @@ export default {
     beforeRemove(file, fileList) {
       return this.$confirm(`确定移除 ${ file.name }?`);
     },
+    //获取token
+    getTokenFromCookie() {
+      const name = "Admin-Token=";
+      const decodedCookie = decodeURIComponent(document.cookie);
+      const cookieArray = decodedCookie.split(';');
+      for (let i = 0; i < cookieArray.length; i++) {
+        let cookie = cookieArray[i].trim();
+        if (cookie.indexOf(name) === 0) {
+          return cookie.substring(name.length, cookie.length); // 返回 token
+        }
+      }
+      return ""; // 如果没有找到 token,返回空字符串
+    },
+    //设置token
+    setHeaders() {
+      this.token = this.getTokenFromCookie(); // 从 cookie 中获取 token
+      this.headers = { token: this.token }; // 设置 headers
+      console.log(this.headers); // 打印 headers
+    },
+    //上传成功以后
+    handleUploadSuccess(response) {
+      this.form.other.push(response.data.imgUrl)
+      console.log('上传成功:', response);
+      console.log(this.form.other);
+    },
     //提交表单
     addData(){
-      console.log(this.form);
-      //1.先验证用户是否已经存在
-      this.$store.dispatch('userMember/verifyUserInfo',{user_name:this.form.user_name}).then(res=>{
-        if(res.code==0){
-          //如果code为0表示用户不存在,提交表单
-          this.$store.dispatch('userMember/createUser',this.form).then(res=>{
-            console.log(res);
+      //1.格式化时间戳
+      this.form.birthday = formatLocalDate(this.form.birthday);
+      if(this.form.long_time==0){
+        this.form.from_time = formatLocalDate(this.timeList[0]);
+        this.form.to_time = formatLocalDate(this.timeList[1]);
+      }else{
+        this.form.from_time = "";
+        this.form.to_time = "";
+      }
+      //2.开始验证
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          //3.验证用户是否已经存在
+          this.$store.dispatch('userMember/verifyUserInfo',{user_name:this.form.user_name}).then(res=>{
+            if(res.code==0){
+              //如果code为0表示用户不存在,提交表单
+              this.$store.dispatch('userMember/createUser',this.form).then(res=>{
+                if(res.code==200){
+                  console.log(res);
+                  this.$message({
+                    type: 'success',
+                    message: '用户添加成功!'
+                  });
+                  this.goList();
+                }else{
+                  this.$message({
+                    type: 'warning',
+                    message: res.message
+                  });
+                }
+              })
+            }else if(res.code==200){
+              //如果code==200 表示用户存在,阻止进一步提交
+              this.$message({
+                type: 'warning',
+                message: '该账号已被注册,请更换其他账号!'
+              });
+            }
+          }).catch(error=>{
             this.$message({
-              type: 'success',
-              message: '用户添加成功!'
+              type: 'warning',
+              message: '网络错误,请重试!'
             });
-            this.goList();
           })
-        }else if(res.code==200){
-          //如果code==200 表示用户存在,阻止进一步提交
-          this.$message({
-            type: 'warning',
-            message: '该账号已被注册,请更换其他账号!'
-          });
         }
-      }).catch(error=>{
-        this.$message({
-          type: 'info',
-          message: '网络错误,请重试!'
-        });
       })
     },
     //提交表单 start ------------------------------------------------------------>
@@ -414,39 +476,86 @@ export default {
         this.form.role_id = res.data.role_id;
         this.form.real_name = res.data.real_name;
         this.form.mobile = res.data.mobile;
-
+        this.form.number = res.data.number;
+        this.photoUrl = res.data.avatar;
+        this.form.avatar = res.data.avatar;
+        this.form.id_card = res.data.id_card;
+        this.form.birthday = res.data.birthday;
+        //还原有效期
+        if(res.data.long_time==0){
+          this.timeList = [
+            res.data.from_time,
+            res.data.to_time
+          ]
+          this.form.from_time = res.data.from_time;
+          this.form.to_time = res.data.to_time;
+          this.form.long_time = 0;
+        }else{
+          this.form.from_time = "";
+          this.form.to_time = "";
+          this.form.long_time = 1;
+        }
+        this.form.qq = res.data.qq;
+        this.form.email = res.data.email;
+        this.form.address = res.data.address;
+        this.form.zip_code = res.data.zip_code;
+        this.form.remark = res.data.remark;
+        this.form.address_arr_id = res.data.address_arr_id;
+        this.form.native_place_arr_id = res.data.native_place_arr_id;
+        // 处理文件列表
+        const fileArrayString = res.data.other; // 假设这是一个字符串格式的数组
+        const fileArray = JSON.parse(fileArrayString); // 解析为数组
+        this.form.other.push(...fileArray); // 将解析出来的值 push 到 this.form.other
+        // 将文件列表赋值给 otherList,生成默认文件名
+        this.otherList = fileArray.map((url, index) => ({
+          name: `文件${index + 1}`, // 生成文件名
+          url: url,                // 文件的 URL
+          status: 'success'        // 设置状态为 success
+        }));
       }).catch(error=>{
         this.$message({
-          type: 'info',
+          type: 'warning',
           message: '网络错误,请重试!'
         });
       })
     },
     //修改用户
     editData(){
-      this.$store.dispatch('userMember/verifyUserInfo',{editId:this.editId,user_name:this.form.user_name}).then(res=>{
-        if(res.code==0){
-          //如果code为0表示用户不存在,提交表单
-          this.$store.dispatch('userMember/createUser',this.form).then(res=>{
-            console.log(res);
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          //1.验证用户是否存在
+          this.$store.dispatch('userMember/verifyUserInfo',{id:this.editId,user_name:this.form.user_name}).then(res=>{
+            if(res.code==0){
+              console.log(this.form);
+              this.form.address_arr_id = JSON.parse(this.form.address_arr_id);
+              this.form.native_place_arr_id = JSON.parse(this.form.native_place_arr_id);
+
+              //2.设置修改的用户id
+              this.form.id = this.editId;
+              //3.提交用户修改
+              //如果code为0表示用户不存在,提交表单
+              this.$store.dispatch('userMember/updateUser',this.form).then(res=>{
+                console.log(res);
+                this.$message({
+                  type: 'success',
+                  message: '用户添加成功!'
+                });
+                this.goList();
+              })
+            }else if(res.code==200){
+              //如果code==200 表示用户存在,阻止进一步提交
+              this.$message({
+                type: 'warning',
+                message: '该账号已被注册,请更换其他账号!'
+              });
+            }
+          }).catch(error=>{
             this.$message({
-              type: 'success',
-              message: '用户添加成功!'
+              type: 'warning',
+              message: '网络错误,请重试!'
             });
-            this.goList();
           })
-        }else if(res.code==200){
-          //如果code==200 表示用户存在,阻止进一步提交
-          this.$message({
-            type: 'warning',
-            message: '该账号已被注册,请更换其他账号!'
-          });
         }
-      }).catch(error=>{
-        this.$message({
-          type: 'info',
-          message: '网络错误,请重试!'
-        });
       })
     },
     //编辑表单 end ------------------------------------------------------------>
@@ -466,7 +575,8 @@ export default {
     }else{
       console.log("添加用户!")
     }
-    
+    //设置token
+    this.setHeaders(); // 在组件挂载时设置 headers
   }
 };
 </script>

+ 556 - 5
src/views/role/components/userPolitician.vue

@@ -1,23 +1,574 @@
 <template>
-  <div>
-    政务会员
+  <div class="mainBox">
+    <div class="layerBox">
+      <el-form ref="form" :model="form" :rules="loginRules" class="login-form" autocomplete="on" label-position="left" label-width="120px">
+        <div class="formDiv">
+          <!--选择角色 start------------------------------------------>
+          <el-form-item label="所属角色:" :label-width="formLabelWidth" prop="role_id" class="custom-align-right">
+            <div class="formLabelFloatBox">
+              <el-select v-model="form.role_id" placeholder="请选择..">
+                <el-option
+                  v-for="item in role_idArr"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value">
+                </el-option>
+              </el-select>
+            </div>
+          </el-form-item>
+          <!--选择角色 end------------------------------------------>
+          <el-form-item label="登录账号:" :label-width="formLabelWidth" prop="user_name" class="custom-align-right">
+            <el-input v-model="form.user_name" autocomplete="off" placeholder="请输入登录账号.."></el-input>
+          </el-form-item>
+          <div v-if="editId==''">
+            <!--新密码 start------------------------------------------>
+            <div class="PasswordBox">
+              <el-form-item prop="password" label="登录密码:"  class="custom-align-right">
+                <div class="PasswordBody">
+                  <el-input
+                    :key="passwordType1"
+                    ref="password1"
+                    v-model="form.password"
+                    :type="passwordType1"
+                    placeholder="请输入密码"
+                    name="password"
+                    tabindex="2"
+                    autocomplete="off"
+                    @blur="capsTooltip2 = false"
+                  />
+                  <span class="show-pwd" @click="showPwd(1)">
+                    <svg-icon :icon-class="passwordType1 === 'password' ? 'eye' : 'eye-open'" />
+                  </span>
+                </div>
+              </el-form-item>
+            </div>
+            <!--新密码 end------------------------------------------>
+            <!--新密码 start------------------------------------------>
+            <div class="PasswordBox">
+              <el-form-item prop="confirm_password" label="确认密码:"  class="custom-align-right">
+                <div class="PasswordBody">
+                  <el-input
+                    :key="passwordType2"
+                    ref="password2"
+                    v-model="form.confirm_password"
+                    :type="passwordType2"
+                    placeholder="请输入密码"
+                    name="password"
+                    tabindex="2"
+                    autocomplete="off"
+                    @blur="capsTooltip2 = false"
+                  />
+                  <span class="show-pwd" @click="showPwd(2)">
+                    <svg-icon :icon-class="passwordType2 === 'password' ? 'eye' : 'eye-open'" />
+                  </span>
+                </div>
+              </el-form-item>
+            </div>
+            <!--新密码 end------------------------------------------>
+          </div>
+          <el-form-item label="行政级别:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input autocomplete="off" placeholder="请输入企业名称.."></el-input>
+          </el-form-item>
+          <el-form-item label="单位名称:" :label-width="formLabelWidth" prop="business_name" class="custom-align-right">
+            <el-input v-model="form.business_name" autocomplete="off" placeholder="请输入单位名称.."></el-input>
+          </el-form-item>
+          <el-form-item label="详细地址:" :label-width="formLabelWidth" prop="address_arr_id" class="custom-align-right">
+            <CityCascader v-model="form.address_arr_id" @update-city-id="update_address_arr_id"></CityCascader>
+          </el-form-item>
+          <el-form-item label="负责人:" :label-width="formLabelWidth" prop="real_name" class="custom-align-right">
+            <el-input v-model="form.real_name" autocomplete="off" placeholder="请输入负责人姓名.."></el-input>
+          </el-form-item>
+          <el-form-item label="负责人职务:" :label-width="formLabelWidth" prop="position" class="custom-align-right">
+            <el-input v-model="form.position" autocomplete="off" placeholder="请输入负责人职务.."></el-input>
+          </el-form-item>
+          <el-form-item label="负责人电话:" :label-width="formLabelWidth" prop="mobile" class="custom-align-right">
+            <el-input v-model="form.mobile" autocomplete="off" placeholder="请输入负责人联系电话.."></el-input>
+          </el-form-item>
+          <el-form-item label="负责人身份证:" :label-width="formLabelWidth" prop="id_card" class="custom-align-right">
+            <el-input v-model="form.id_card" autocomplete="off" placeholder="请输入负责人身份证号.."></el-input>
+          </el-form-item>
+          <el-form-item label="法人:" :label-width="formLabelWidth" prop="legal_person_real_name" class="custom-align-right">
+            <el-input v-model="form.legal_person_real_name" autocomplete="off" placeholder="请输入法人姓名.."></el-input>
+          </el-form-item>
+          <el-form-item label="法人电话:" :label-width="formLabelWidth" prop="legal_person_mobile" class="custom-align-right">
+            <el-input v-model="form.legal_person_mobile" autocomplete="off" placeholder="请输入法人联系电话.."></el-input>
+          </el-form-item>
+          <el-form-item label="法人身份证:" :label-width="formLabelWidth" prop="legal_person_id_card" class="custom-align-right">
+            <el-input v-model="form.legal_person_id_card" autocomplete="off" placeholder="请输入法人身份证号.."></el-input>
+          </el-form-item>
+          <el-form-item label="有效期:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-date-picker
+              v-model="timeList"
+              type="daterange"
+              :disabled="form.long_time === 1"
+              range-separator="至"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+              :picker-options="pickerOptions">
+            </el-date-picker>
+            <el-checkbox v-model="form.long_time" :true-label="1" :false-label="0" class="longTimeCheckbox">无限期</el-checkbox>
+          </el-form-item>
+          <el-form-item label="传真:" :label-width="formLabelWidth" prop="fax" class="custom-align-right">
+            <el-input v-model="form.fax" autocomplete="off" placeholder="请输入传真号码.."></el-input>
+          </el-form-item>
+          <el-form-item label="邮编:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input v-model="form.zip_code" autocomplete="off" placeholder="请输入邮编.."></el-input>
+          </el-form-item>
+          <el-form-item label="QQ:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input v-model="form.qq" autocomplete="off" placeholder="请输入QQ号.."></el-input>
+          </el-form-item>
+          <el-form-item label="电子邮箱:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input v-model="form.email" autocomplete="off" placeholder="请输入电子邮箱.."></el-input>
+          </el-form-item>
+          <el-form-item label="相关资料:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-upload
+              class="upload-demo"
+              :action="uploadFileUrl"
+              :headers="headers"
+              :on-preview="handlePreview"
+              :on-remove="handleRemove"
+              :before-remove="beforeRemove"
+              :on-success="handleUploadSuccess"
+              multiple
+              :limit="30"
+              :on-exceed="handleExceed"
+              :file-list="otherList">
+              <el-button size="small" type="primary">点击上传</el-button>
+              <div slot="tip" class="el-upload__tip">每张图片最大1MB,最多上传30张图片。</div>
+            </el-upload>
+          </el-form-item>
+          <el-form-item label="提示词:" :label-width="formLabelWidth" prop="" class="custom-align-right">
+            <el-input type="textarea" v-model="form.remark" class="custom-textarea"></el-input>
+          </el-form-item>
+        </div>
+      </el-form>
+    </div>  
+    <div class="bottomBtnBox">
+      <el-button type="info" @click="goList">返回</el-button>
+      <el-button type="primary" @click="addData" v-if="editId==''">提交</el-button>
+      <el-button type="primary" @click="editData" v-else>修改</el-button>
+    </div>
   </div>
 </template>
 
 <script>
+// 引入公用样式
+import '@/styles/global.less';
+// 引入baseUrl
+import URL from '@/utils/baseUrl';
+//城市级联选择器
+import CityCascader from './CityCascader';
+//格式化时间
+import { formatLocalDate } from '@/utils/public';
+
 
 export default {
+  components: {
+    CityCascader, //城市级联选择器
+  },
   data() {
+    // 配置验证规则:用于表单验证
+    const validatePassword = (rule, value, callback) => {
+      if (value.length < 6) {
+        callback(new Error('密码不能低于6位!'))
+      } else {
+        callback()
+      }
+    }
+    const validateEmpty = (rule,value,callback) => {
+      if (!value || value.trim() === "") {
+        callback(new Error('该项不能为空!'));
+      } else {
+        callback();
+      }
+    }
+    const validateArray = (rule,value,callback) => {
+      if (value.length == 0) {
+        callback(new Error('该项不能为空!'))
+      } else {
+        callback()
+      }
+    }
     return {
-      num:1
+      formLabelWidth:"120px",
+      editId:"",
+      uploadFileUrl:URL.testUrl+"/public/uploadFile",//获得上传地址
+      headers: {},
+      form:{
+        type_id:2,//政务会员
+        role_id:"",//角色id 
+        user_name:"",//登录账号
+        password:"",//密码
+        confirm_password:"",//确认密码
+        real_name:"",//真实姓名
+        id_card:"",//身份证号
+        mobile:"",//手机号
+        address_arr_id:"",//工作区域
+        from_time:"",//有效期开始时间
+        to_time:"",//有效期结束时间
+        long_time:0,//是否为长期 //长期1:长期 0:非长期
+        qq:"",//QQ
+        email:"",//电子邮箱
+        other:[],//相关资料
+        remark:"",//提示词
+        administrative_unit_arr_id:[0],//行政级别
+        //企业相关字段
+        fax:"",//传真
+        business_name:"",//企业名称
+        position:"",//负责人职务
+        legal_person_real_name:"",//法人姓名
+        legal_person_mobile:"",//法人手机号
+        legal_person_id_card:"",//法人身份证号
+      },
+      timeList:[],//时间段
+      otherList:[],//相关资料列表
+      role_idArr:[],//角色id池
+      //密码验证
+      capsTooltip1: false,
+      capsTooltip2: false,
+      passwordType1: 'password',
+      passwordType2: 'password',
+      //配置from表单验证规则
+      loginRules: { 
+        //1.角色id
+        role_id: [{ required: true, trigger: 'blur', validator: validateArray }],
+        //2.登录账号
+        user_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //3.密码和确认密码
+        password: [{ required: true, trigger: 'blur', validator: validatePassword }],
+        confirm_password: [{ required: true, trigger: 'blur', validator: validatePassword }],
+        //4.调研员编号
+        number: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //5.真实姓名
+        real_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //6.手机号
+        mobile: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //7.身份证号
+        id_card: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //8.性别
+        gender: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //9.手机号
+        mobile: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //10.工作区域
+        address_arr_id: [{ required: true, trigger: 'blur', validator: validateArray }],
+        //11.企业名称
+        business_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //12.负责人职务
+        position: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //12.法人姓名
+        legal_person_real_name: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //13.法人电话
+        legal_person_mobile: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //14.法人身份证号
+        legal_person_id_card: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+        //15.行政级别
+        administrative_unit_arr_id: [{ required: true, trigger: 'blur', validator: validateEmpty }],
+      },
+      //时间跨度
+      pickerOptions: {
+        selectableRange: '1900-01-01 to 2100-12-31', // 允许选择的日期范围
+        disabledDate(time) {
+          return time.getTime() < Date.now() - 86400000; // 禁用今天之前的日期
+        },
+      },
     };
   },
   methods: {
-    
+    //1.表单收集 start ------------------------------------------------------------>
+    //1.1切换密码框的显示与隐藏
+    showPwd(num) {
+      const passwordTypeKey = 'passwordType' + num; //动态生成 passwordType 的键
+      const passwordRefKey = 'password' + num; //动态生成 password 的引用
+      // 切换密码类型
+      if (this[passwordTypeKey] === 'password') {
+        this[passwordTypeKey] = ''; //显示密码
+      } else {
+        this[passwordTypeKey] = 'password'; //隐藏密码
+      }
+      // 使用 $nextTick 聚焦到对应的密码输入框
+      this.$nextTick(() => {
+        this.$refs[passwordRefKey].focus(); //聚焦到对应的密码输入框
+      });
+    },
+    //1.2获得角色列表池
+    getRoleList(){
+      let data = {
+        page:1,
+        pageSize:100
+      }
+      this.$store.dispatch('userRole/roleList',data).then(res=>{
+        this.role_idArr = res.data.rows.map(item => ({
+          value: item.id,
+          label: item.role_name 
+        }));
+      }).catch(error=>{
+        this.$message({
+          type: 'warning',
+          message: '网络错误,请重试!'
+        });
+      })
+    },
+    //1.3更新工作区域
+    update_address_arr_id(value){
+      console.log("工作区域ID已更新:", value);
+      this.form.address_arr_id = value;
+    },
+    //1.5重置表单
+    clearData(){
+      
+    },
+    //表单收集 end ------------------------------------------------------------>
+    //2.提交表单 start ------------------------------------------------------------>
+    //2.3 多文件上传
+    handleRemove(file, fileList) {
+      console.log(file, fileList);
+    },
+    handlePreview(file) {
+      console.log(file);
+    },
+    handleExceed(files, fileList) {
+      this.$message.warning(`当前限制选择 30 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
+    },
+    beforeRemove(file, fileList) {
+      return this.$confirm(`确定移除 ${ file.name }?`);
+    },
+    //获取token
+    getTokenFromCookie() {
+      const name = "Admin-Token=";
+      const decodedCookie = decodeURIComponent(document.cookie);
+      const cookieArray = decodedCookie.split(';');
+      for (let i = 0; i < cookieArray.length; i++) {
+        let cookie = cookieArray[i].trim();
+        if (cookie.indexOf(name) === 0) {
+          return cookie.substring(name.length, cookie.length); // 返回 token
+        }
+      }
+      return ""; // 如果没有找到 token,返回空字符串
+    },
+    //设置token
+    setHeaders() {
+      this.token = this.getTokenFromCookie(); // 从 cookie 中获取 token
+      this.headers = { token: this.token }; // 设置 headers
+      console.log(this.headers); // 打印 headers
+    },
+    //上传成功以后
+    handleUploadSuccess(response) {
+      this.form.other.push(response.data.imgUrl)
+      console.log('上传成功:', response);
+      console.log(this.form.other);
+    },
+    //提交表单
+    addData(){
+      //1.格式化时间戳
+      if(this.form.long_time==0){
+        this.form.from_time = formatLocalDate(this.timeList[0]);
+        this.form.to_time = formatLocalDate(this.timeList[1]);
+      }else{
+        this.form.from_time = "";
+        this.form.to_time = "";
+      }
+      //2.开始验证
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          //3.验证用户是否已经存在
+          this.$store.dispatch('userMember/verifyUserInfo',{user_name:this.form.user_name}).then(res=>{
+            if(res.code==0){
+              //如果code为0表示用户不存在,提交表单
+              this.$store.dispatch('userMember/createUser',this.form).then(res=>{
+                if(res.code==200){
+                  console.log(res);
+                  this.$message({
+                    type: 'success',
+                    message: '用户添加成功!'
+                  });
+                  this.goList();
+                }else{
+                  this.$message({
+                    type: 'warning',
+                    message: res.message
+                  });
+                }
+              })
+            }else if(res.code==200){
+              //如果code==200 表示用户存在,阻止进一步提交
+              this.$message({
+                type: 'warning',
+                message: '该账号已被注册,请更换其他账号!'
+              });
+            }
+          }).catch(error=>{
+            this.$message({
+              type: 'warning',
+              message: '网络错误,请重试!'
+            });
+          })
+        }
+      })
+    },
+    //提交表单 start ------------------------------------------------------------>
+    //3.编辑表单 start ------------------------------------------------------------>
+    //获得用户信息
+    getUserInfo(){
+      this.$store.dispatch('userMember/getUser',{id:this.editId}).then(res=>{
+        console.log(res);
+        //回显数据
+        this.form.type_id = res.data.type_id;
+        this.form.user_name = res.data.user_name;
+        this.form.role_id = res.data.role_id;
+        this.form.real_name = res.data.real_name;
+        this.form.mobile = res.data.mobile;
+        this.form.number = res.data.number;
+        this.form.avatar = res.data.avatar;
+        this.form.id_card = res.data.id_card;
+        this.form.fax = res.data.fax;
+        this.form.legal_person_id_card = res.data.legal_person_id_card;
+        this.form.legal_person_mobile = res.data.legal_person_mobile;
+        this.form.legal_person_real_name = res.data.legal_person_real_name;
+        this.form.position = res.data.position;
+        this.form.business_name = res.data.business_name;
+        //还原有效期
+        if(res.data.long_time==0){
+          this.timeList = [
+            res.data.from_time,
+            res.data.to_time
+          ]
+          this.form.from_time = res.data.from_time;
+          this.form.to_time = res.data.to_time;
+          this.form.long_time = 0;
+        }else{
+          this.form.from_time = "";
+          this.form.to_time = "";
+          this.form.long_time = 1;
+        }
+        this.form.qq = res.data.qq;
+        this.form.email = res.data.email;
+        this.form.zip_code = res.data.zip_code;
+        this.form.remark = res.data.remark;
+        this.form.address_arr_id = res.data.address_arr_id;
+        
+        // 处理文件列表
+        const fileArrayString = res.data.other; // 假设这是一个字符串格式的数组
+        const fileArray = JSON.parse(fileArrayString); // 解析为数组
+        this.form.other.push(...fileArray); // 将解析出来的值 push 到 this.form.other
+        // 将文件列表赋值给 otherList,生成默认文件名
+        this.otherList = fileArray.map((url, index) => ({
+          name: `文件${index + 1}`, // 生成文件名
+          url: url,                // 文件的 URL
+          status: 'success'        // 设置状态为 success
+        }));
+      }).catch(error=>{
+        this.$message({
+          type: 'warning',
+          message: '网络错误,请重试!'
+        });
+      })
+    },
+    //修改用户
+    editData(){
+      //1.格式化时间戳
+      if(this.form.long_time==0){
+        this.form.from_time = formatLocalDate(this.timeList[0]);
+        this.form.to_time = formatLocalDate(this.timeList[1]);
+      }else{
+        this.form.from_time = "";
+        this.form.to_time = "";
+      }
+      //2.提交修改的数据
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          //1.验证用户是否存在
+          this.$store.dispatch('userMember/verifyUserInfo',{id:this.editId,user_name:this.form.user_name}).then(res=>{
+            if(res.code==0){
+              console.log(this.form);
+              this.form.address_arr_id = JSON.parse(this.form.address_arr_id);
+              //2.设置修改的用户id
+              this.form.id = this.editId;
+              //3.提交用户修改
+              //如果code为0表示用户不存在,提交表单
+              this.$store.dispatch('userMember/updateUser',this.form).then(res=>{
+                console.log(res);
+                this.$message({
+                  type: 'success',
+                  message: '用户添加成功!'
+                });
+                this.goList();
+              })
+            }else if(res.code==200){
+              //如果code==200 表示用户存在,阻止进一步提交
+              this.$message({
+                type: 'warning',
+                message: '该账号已被注册,请更换其他账号!'
+              });
+            }
+          }).catch(error=>{
+            this.$message({
+              type: 'warning',
+              message: '网络错误,请重试!'
+            });
+          })
+        }
+      })
+    },
+    //编辑表单 end ------------------------------------------------------------>
+    goList(){
+      this.$router.push({
+        path: '/userList',
+      });
+    },
   },
+  mounted(){
+    this.getRoleList();
+    //判断是新建还是回显
+    if(this.$route.query.id!=undefined){
+      this.editId = this.$route.query.id;
+      console.log("编辑用户!")
+      this.getUserInfo();
+    }else{
+      console.log("添加用户!")
+    }
+    //设置token
+    this.setHeaders(); // 在组件挂载时设置 headers
+  }
 };
 </script>
 
 <style scoped lang="less">
-  
+  .PasswordBox {
+    display: flex;
+    align-items: center;
+    .el-form-item {
+      flex: 1;
+    }
+    .PasswordTitle {
+      width:120px;
+      text-align: right;
+      margin-right: 10px;
+      margin-bottom:22px;
+    }
+    .PasswordBody {
+      flex: 1;
+      display: flex;
+      align-items: center;
+    }
+    .show-pwd {
+      margin-left: 10px;
+    }
+  }
+  .longTimeCheckbox {
+    margin-left: 10px;
+  }
+  //执行v-deep穿透scope选择器 start------------------------------------------------------------>*/
+  ::v-deep .custom-form-item > .el-form-item__label {
+    line-height: 140px !important;
+  }
+  ::v-deep .custom-textarea .el-textarea__inner {
+    resize: none; /* 禁止用户拖拽调整大小 */
+  }
+  ::v-deep .custom-align-right .el-form-item__label {
+    text-align: right; /* 设置标签文字右对齐 */
+  }
+  ::v-deep .el-select {
+    width: 100%; /* 禁止用户拖拽调整大小 */
+  }
+  //执行v-deep穿透scope选择器 end------------------------------------------------------------>*/
 </style>

+ 33 - 10
src/views/role/creatUser.vue

@@ -3,19 +3,22 @@
     <div class="layerBox">
       <tableTitle :name="tableDivTitle"/>
       <div>
-        <el-radio v-model="userType" label="10000">管理员</el-radio>
-        <el-radio v-model="userType" label="4">调研员</el-radio>
-        <el-radio v-model="userType" label="1">个人会员</el-radio>
-        <el-radio v-model="userType" label="3">企业会员</el-radio>
-        <el-radio v-model="userType" label="2">政务会员</el-radio>  
+        <el-radio-group v-model="userType">
+          <el-radio v-for="option in radioOptions" 
+                     :key="option.label" 
+                     :label="option.value" 
+                     :disabled="isDisabled(option.value)">
+            {{ option.label }}
+          </el-radio>
+        </el-radio-group>
       </div>
     </div>
     <!-- 根据 userType 的值动态显示组件 -->
     <user-admin v-if="userType === '10000'" />
     <user-investigate v-if="userType === '4'" />
     <user-default v-if="userType === '1'" />
-    <user-enterprise v-if="userType === '2'" />
-    <user-politician v-if="userType === '3'" />
+    <user-enterprise v-if="userType === '3'" />
+    <user-politician v-if="userType === '2'" />
   </div>
 </template>
 
@@ -24,7 +27,7 @@
 import tableTitle from './components/tableTitle';
 import userAdmin from './components/userAdmin'; // 引入管理员组件
 import userInvestigate from './components/userInvestigate'; // 引入调研员组件
-import userDefault from './components/userDefault'; // 引入调研员组件
+import userDefault from './components/userDefault'; // 引入个人会员组件
 import userEnterprise from './components/userEnterprise'; // 引入企业会员组件
 import userPolitician from './components/userPolitician'; // 引入政务会员组件
 // 引入公用样式
@@ -42,14 +45,34 @@ export default {
   data() {
     return {
       tableDivTitle: "选择用户类型",
-      userType: "10000" // 用户类型
+      userType: "10000", // 用户类型
+      radioOptions: [
+        { label: '管理员', value: '10000' },
+        { label: '调研员', value: '4' },
+        { label: '个人会员', value: '1' },
+        { label: '企业会员', value: '3' },
+        { label: '政务会员', value: '2' }
+      ]
     };
   },
   methods: {
-    // 其他方法
+    isDisabled(value) {
+      // 如果 type_id 存在,则禁用与 userType 不对应的选项
+      if (this.$route.query.type_id) {
+        return value !== this.userType;
+      }
+      // 如果 type_id 不存在,则允许所有选项
+      return false;
+    }
   },
   mounted() {
     // 其他逻辑
+    if (this.$route.query.type_id != undefined) {
+      this.userType = String(this.$route.query.type_id);
+      console.log("编辑用户!");
+    } else {
+      console.log("添加用户!");
+    }
   },
 };
 </script>

+ 4 - 3
src/views/role/userList.vue

@@ -71,7 +71,7 @@
             <el-table-column fixed="right" label="操作" width="200" header-align="center">
               <template slot-scope="scope">
                 <div class="listBtnBox">
-                  <div class="listEditBtn" @click="goEdit(scope.row.id)"><i class="el-icon-edit-outline"></i>编辑</div>
+                  <div class="listEditBtn" @click="goEdit(scope.row.id,scope.row.type_id)"><i class="el-icon-edit-outline"></i>编辑</div>
                 </div>
               </template>
             </el-table-column>
@@ -210,9 +210,10 @@ export default {
         path: '/creatUser',
       });
     },
-    goEdit(id){
+    goEdit(id,type_id){
       let data = {
-        id:id
+        id:id,
+        type_id:type_id
       }
       this.$router.push({
         path: '/creatUser',