若依 ruoyi 默认显示搜索框 保留搜索条件 HeaderSearch/index.vue

该文章展示了一个Vue组件HeaderSearch的代码实现,包括使用fuse.js进行模糊搜索,处理搜索框的显示与隐藏,以及搜索结果的筛选和路由跳转。搜索框默认展开,且在搜索后保持开启状态,保留上一次的搜索结果。

HeaderSearch/index.vue

修改部分代码

<template>
  <div :class="{'show':show}" class="header-search">
    <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
    <el-select
      ref="headerSearchSelect"
      v-model="search"
      :remote-method="querySearch"
      filterable
      default-first-option
      remote
      placeholder="菜单快捷搜索"
      class="header-search-select"
      @change="change"
    >
      <el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" />
    </el-select>
  </div>
</template>

<script>
// fuse is a lightweight fuzzy-search module
// make search results more in line with expectations
import Fuse from 'fuse.js/dist/fuse.min.js'
import path from 'path'

export default {
  name: 'HeaderSearch',
  data() {
    return {
      search: '',
      options: [],
      searchPool: [],
      show: true,//右上角搜索框 默认开启
      fuse: undefined
    }
  },
  computed: {
    routes() {
      return this.$store.getters.permission_routes
    }
  },
  watch: {
    routes() {
      this.searchPool = this.generateRoutes(this.routes)
    },
    searchPool(list) {
      this.initFuse(list)
    },
    show(value) {
      if (value) {
        document.body.addEventListener('click', this.close)
      } else {
        document.body.removeEventListener('click', this.close)
      }
    }
  },
  mounted() {
    this.searchPool = this.generateRoutes(this.routes)
  },
  methods: {
    click() {
      this.show = !this.show
      if (this.show) {
        this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
      }
    },
    close() {
      this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
      // this.options = [] //清空搜索结果;注释掉:保留上一次的搜索结果
      //this.show = false //false 关闭搜索框;注释掉:搜索框停留
    },
    change(val) {
      const path = val.path;
      if(this.ishttp(val.path)) {
        // http(s):// 路径新窗口打开
        const pindex = path.indexOf("http");
        window.open(path.substr(pindex, path.length), "_blank");
      } else {
        this.$router.push(val.path)
      }
      //this.search = '' //清空搜索词;注释掉:保留上一次的搜索词
      //this.options = [] //清空搜索结果;注释掉:保留上一次的搜索结果
      this.$nextTick(() => {
        //this.show = false //false 关闭搜索框;注释掉:搜索框停留
      })
    },
    initFuse(list) {
      this.fuse = new Fuse(list, {
        shouldSort: true,
        threshold: 0.4,
        location: 0,
        distance: 100,
        minMatchCharLength: 1,
        keys: [{
          name: 'title',
          weight: 0.7
        }, {
          name: 'path',
          weight: 0.3
        }]
      })
    },
    // Filter out the routes that can be displayed in the sidebar
    // And generate the internationalized title
    generateRoutes(routes, basePath = '/', prefixTitle = []) {
      let res = []

      for (const router of routes) {
        // skip hidden router
        if (router.hidden) { continue }

        const data = {
          path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path,
          title: [...prefixTitle]
        }

        if (router.meta && router.meta.title) {
          data.title = [...data.title, router.meta.title]

          if (router.redirect !== 'noRedirect') {
            // only push the routes with title
            // special case: need to exclude parent router without redirect
            res.push(data)
          }
        }

        // recursive child routes
        if (router.children) {
          const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
          if (tempRoutes.length >= 1) {
            res = [...res, ...tempRoutes]
          }
        }
      }
      return res
    },
    querySearch(query) {
      if (query !== '') {
        this.options = this.fuse.search(query)
      } else {
        this.options = []
      }
    },
    ishttp(url) {
      return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1
    }
  }
}
</script>

<style lang="scss" scoped>
.header-search {
  font-size: 0 !important;

  .search-icon {
    cursor: pointer;
    font-size: 18px;
    vertical-align: middle;
  }

  .header-search-select {
    font-size: 18px;
    transition: width 0.2s;
    width: 0;
    overflow: hidden;
    background: transparent;
    border-radius: 0;
    display: inline-block;
    vertical-align: middle;

    ::v-deep .el-input__inner {
      border-radius: 0;
      border: 0;
      padding-left: 0;
      padding-right: 0;
      box-shadow: none !important;
      border-bottom: 1px solid #d9d9d9;
      vertical-align: middle;
    }
  }

  &.show {
    .header-search-select {
      width: 210px;
      margin-left: 10px;
    }
  }
}
</style>

默认展开搜索框

不关闭搜索框

保留上一次的搜索结果

<template> <div class="app-container-box"> <div class="app-row-left" :class="{ collapsed: !showLeftPanel }"> <DeptTree inputPlaceholder="请输入名称" @node-click="handleNodeClick" @default-selected="handleDefaultSelected" ref="deptTreeRef" /> </div> <!-- 手柄:始终显示,位置随左侧状态变化 --> <div class="sidebar-toggle-handle" :class="{ expanded: showLeftPanel, collapsed: !showLeftPanel }" @click="toggleLeftPanel" > <el-icon> <component :is="showLeftPanel ? 'ArrowLeft' : 'ArrowRight'" /> </el-icon> </div> <div class="app-row-right"> <!-- 表单区域 --> <el-form :model="queryParams" ref="queryRef" label-width="auto" class="search-form"> <!-- 第一行:主要筛选 + 操作按钮 --> <div class="form-row"> <el-form-item label="用户名称" prop="userName"> <el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable style="width: 240px" @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="用户昵称" prop="nickName"> <el-input v-model="queryParams.nickName" placeholder="请输入用户昵称" clearable style="width: 240px" @keyup.enter="handleQuery" /> </el-form-item> <!-- 操作按钮固定在右侧 --> <el-form-item> <div class="form-actions"> <el-button type="primary" icon="Search" @click="handleQuery" >搜索</el-button > <el-button icon="Refresh" @click="resetQuery">重置</el-button> <!-- <el-button text type="primary" @click="toggleExpand" icon="Filter"> {{ isExpanded ? '收起' : '筛选' }} </el-button> --> </div> </el-form-item> </div> <!-- 第二行:额外筛选项(仅在展开时显示--> <!-- <div v-if="isExpanded" class="form-row expanded-filters"> </div> --> </el-form> <!-- 插入统计卡片组件 --> <!-- <StatCards :stats="statData" /> --> <!-- 表格 + 列设置容器(可滚动) --> <div class="table-wrapper"> <!-- 表格头部:列设置按钮 --> <div class="table-header"> <div class="header-left"> <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:user:add']" >新增</el-button > </div> <div class="header-right"> <!-- cache-key 每个页面的列设置请设置 唯一标识 不要重置 --> <ColumnSetting :columns="allColumns" v-model="selectedColumnProps" cache-key="project_list_columns_test" > <template #trigger> <el-icon><Setting /></el-icon> </template> </ColumnSetting> </div> </div> <!-- 动态表格 --> <el-table :data="userList" v-loading="loading" border style="width: 100%" height="100%" @selection-change="handleSelectionChange" > <!-- 1. 多选列 --> <el-table-column v-if="showSelection" type="selection" width="55" align="center" /> <el-table-column v-for="col in visibleColumns" :key="col.prop" :prop="col.prop" :label="col.label" :width="col.width || ''" :min-width="col.minWidth || ''" align="center" show-overflow-tooltip > <!-- 自定义列内容 --> <template #default="{ row }"> <!-- 用户名称 --> <template v-if="col.prop === 'userName'"> <span>{{ row.userName }}</span> </template> <!-- 区域 --> <template v-else-if="col.prop === 'dept.deptName'"> <span>{{ row.dept.deptName }}</span> </template> <!-- 区域级别 --> <template v-else-if="col.prop === 'userClass'"> <div v-if="row.userClass == '1'">市</div> <div v-if="row.userClass == '2'">区</div> <div v-if="row.userClass == '3'">学校</div> <div v-if="row.userClass == '4'">内部账号</div> <div v-if="row.userClass == '5'">API用户</div> </template> <!-- 状态 --> <template v-else-if="col.prop === 'status'"> <el-switch v-model="row.status" active-value="0" inactive-value="1" @change="handleStatusChange(row)" ></el-switch> </template> <!-- 创建时间 --> <template v-else-if="col.prop === 'createTime'"> <span>{{ parseTime(row.createTime) }}</span> </template> <!-- 默认文本 --> <template v-else> {{ row[col.prop] }} </template> </template> </el-table-column> <!-- 操作列(固定右侧,不参与 ColumnSetting)--> <el-table-column label="操作" align="center" fixed="right" min-width="200"> <template #default="{ row }"> <el-tooltip content="修改" placement="top" v-if="row.userId !== 1"> <el-button link type="primary" icon="Edit" @click="handleUpdate(row)" v-hasPermi="['system:user:edit']" ></el-button> </el-tooltip> <el-tooltip content="删除" placement="top" v-if="row.userId !== 1"> <el-button link type="primary" icon="Delete" @click="handleDelete(row)" v-hasPermi="['system:user:remove']" ></el-button> </el-tooltip> <el-tooltip content="重置密码" placement="top" v-if="row.userId !== 1"> <el-button link type="primary" icon="Key" @click="handleResetPwd(srow)" v-hasPermi="['system:user:resetPwd']" ></el-button> </el-tooltip> </template> </el-table-column> </el-table> </div> <pagination v-if="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :pageSizes="[10, 30, 50, 100, 200, 500, 1000]" @pagination="getList" /> </div> <!-- 添加或修改用户配置对话框 --> <el-dialog :title="title" v-model="open" width="800px" append-to-body :close-on-click-modal="false" :before-close="beforeCloseFun" > <el-form :model="form" :rules="rules" ref="userRef" label-width="100px"> <el-row> <el-col :span="12"> <el-form-item label="用户昵称" prop="nickName"> <el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="归属区域" prop="deptId"> <el-tree-select v-model="form.deptId" :data="deptOptions" :props="{ value: 'id', label: 'label', children: 'children', }" value-key="id" placeholder="请选择归属区域" check-strictly filterable @node-click="handleSelectTreeClick" /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item v-if="form.userId == undefined" label="登录名称" prop="userName" > <el-input v-model="form.userName" placeholder="请输入登录名称" maxlength="30" /> </el-form-item> </el-col> <el-col :span="12"> <el-form-item v-if="form.userId == undefined" label="用户密码" prop="password" > <el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password /> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="12"> <el-form-item label="状态"> <el-radio-group v-model="form.status"> <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value" >{{ dict.label }}</el-radio > </el-radio-group> </el-form-item> </el-col> <el-col :span="12"> <el-form-item label="角色" prop="roleIds"> <el-select v-model="form.roleIds" @change="handleRoleClikle" placeholder="请选择" filterable multiple > <el-option v-for="item in roleOptions" :key="item.roleId" :label="item.roleName" :value="item.roleId" :disabled="item.status == 1" ></el-option> </el-select> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="学校" prop="apiSchoolIds"> <el-transfer ref="transferRef" :disable="!form.deptId" v-model="form.apiSchoolIds" filterable :titles="['学校列表', '已选学校']" :button-texts="['取消', '选中']" filter-placeholder="请输入学校名称搜索" :format="{ noChecked: '${total}', hasChecked: '${checked}/${total}', }" :props="{ key: 'schoolId', label: 'schoolName', }" :data="schoolQy" @change="handleChange" > <template #default="{ option }"> <el-tooltip class="item-tooltip" effect="dark" :content="`${option.districtName} - ${option.schoolName}`" placement="top" > <span class="transfer-item-text"> {{ option.districtName }}-{{ option.schoolName }} </span> </el-tooltip> </template> </el-transfer> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item prop="whiteList"> <el-input v-model="form.whiteList" type="textarea" placeholder="请输入内容" ></el-input> <template #label> <span> <el-tooltip content="白名单示例:192.168.2.1,192.168.2.2" placement="top" > <el-icon><question-filled /></el-icon> </el-tooltip> 白名单 </span> </template> </el-form-item> </el-col> </el-row> <el-row> <el-col :span="24"> <el-form-item label="备注"> <el-input v-model="form.remark" type="textarea" placeholder="请输入内容" ></el-input> </el-form-item> </el-col> </el-row> </el-form> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="submitForm">确 定</el-button> <el-button @click="cancel">取 消</el-button> </div> </template> </el-dialog> <!-- 用户导入对话框 --> <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body> <el-upload ref="uploadRef" :limit="1" accept=".xlsx, .xls" :headers="upload.headers" :action="upload.url + '?updateSupport=' + upload.updateSupport" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :auto-upload="false" drag > <el-icon class="el-icon--upload"> <upload-filled /> </el-icon> <div class="el-upload__text">将文件拖到此处,或点击上传</div> <template #tip> <div class="el-upload__tip text-center"> <div class="el-upload__tip"> <el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据 </div> <span>仅允许导入xls、xlsx格式文件。</span> <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline" @click="importTemplate" >下载模板</el-link > </div> </template> </el-upload> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="submitFileForm">确 定</el-button> <el-button @click="upload.open = false">取 消</el-button> </div> </template> </el-dialog> </div> </template> <script setup lang="ts" name="ApiUser"> import DeptTree from '@/components/DeptTreeNewTable' import { taskTypeEnum } from '@/components/export-button/const.ts' import ExportButton from '@/components/export-button/index.vue' import { ref, toRefs, reactive, defineOptions, computed, watch, onMounted } from 'vue' import { changeUserStatus, listUser, resetUserPwd, delUser, getUser, updateUser, addUser, deptTreeSelect, roleGetList, } from '@/api/system/user' import { getListSys, getSchoolDept } from '@/api/city/appAuthorization' import useUserStore from '@/store/modules/user' import { parseTime } from '../../../utils/ruoyi.js' import pdfFile from '@/assets/images/pdf-file.png' import { DateUtils } from '@/utils/dateUtils' import { decryptDes } from '@/utils/des.js' import { decrypt } from '@/utils/rsa.js' import dayjs from 'dayjs' import { isChinese } from '@/utils/ruoyi.js' import drawerComPage from '@/components/drawerCom/drawerComPage.vue' import { getToken } from '@/utils/auth' // Vue 3.3+ 使用 defineOptions defineOptions({ name: 'ApiUser', }) const { proxy } = getCurrentInstance() const { sys_normal_disable, sys_user_school } = proxy.useDict( 'sys_normal_disable', 'sys_user_school', ) // ========== 响应式数据 ========== const showSelection = ref(false) const isCollapsed = ref(false) const loading = ref(false) const total = ref(0) const selectedRows = ref<any[]>([]) const isExpanded = ref(false) const statData = computed(() => { return [ { label: '人数汇总', value: statistics.value.totalUserCount || 0 }, { label: '校园卡账户余额汇总', value: statistics.value.totalCardBalance || 0 }, { label: '校园补助金额余额汇总', value: statistics.value.totalSubsidyBalance || 0 }, ] }) const deptTreeRef = ref() const showLeftPanel = ref(true) const toggleLeftPanel = () => { showLeftPanel.value = !showLeftPanel.value } const ids = ref([]) const single = ref(true) const multiple = ref(true) const open = ref(false) const dialogVisible = ref(false) // 统计信息 const statistics = ref({ totalUserCount: 0, totalCardBalance: 0, totalSubsidyBalance: 0, }) const userList = ref([]) const title = ref('') const statusOptions = [ { value: 1, label: '未审核' }, { value: 2, label: '已审核' }, ] const levelNode = ref() const lastTwoDigits = ref('') const schoolAll = ref([]) const dateRange = ref([]) const deptOptions = ref(undefined) const postOptions = ref([]) const roleOptions = ref([]) const schoolQy = ref([]) // 默认属性配置 const defaultProps = { children: 'systemList', label: 'systemName', value: 'systemId', } /*** 用户导入参数 */ const upload = reactive({ // 是否显示弹出层(用户导入) open: false, // 弹出层标题(用户导入) title: '', // 是否禁用上传 isUploading: false, // 是否更新已经存在的用户数据 updateSupport: 0, // 设置上传的请求头部 headers: { Authorization: 'Bearer ' + getToken() }, // 上传的地址 url: import.meta.env.VITE_APP_BASE_API + '/system/user/importData', }) // ========== 查询参数 ========== const validateWhiteList = (rule, value, callback) => { const regex = /^(\d{1,3}\.){3}\d{1,3}(,\s?(\d{1,3}\.){3}\d{1,3})*$/ // IP 地址格式 if (!value) { return callback(new Error('白名单不能为空')) } if (!regex.test(value)) { return callback(new Error('输入格式错误,请输入格式如:192.168.2.123,192.168.2.124')) } callback() // 验证通过 } const data = reactive({ form: {}, formStatistice: {}, formArray: [], queryParams: { pageNum: 1, pageSize: 10, userName: undefined, phonenumber: undefined, status: undefined, deptId: undefined, userClass: '5', schoolId: undefined, }, rules: { userName: [ { required: true, message: '登录名称不能为空', trigger: 'blur' }, { min: 2, max: 20, message: '用户名称长度必须介于 2 和 20 之间', trigger: 'blur', }, ], postIds: [{ required: true, message: '岗位不能为空', trigger: 'blur' }], nickName: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }], password: [ { required: true, message: '用户密码不能为空', trigger: 'blur' }, { min: 13, max: 100, message: '用户密码长度必须至少 13 位', trigger: 'blur', }, { pattern: /^[^<>"'|\\]+$/, message: '不能包含非法字符:< > " \' \\ |', trigger: 'blur', }, ], deptId: [{ required: true, message: '所属区域不能为空', trigger: 'blur' }], roleIds: [{ required: true, message: '角色不能为空', trigger: 'blur' }], // systemIds: [ // { required: true, message: "应用类型不能为空", trigger: "blur" }, // ], userClass: [{ required: true, message: '市区内容不能为空', trigger: 'blur' }], whiteList: [ { required: true, message: '白名单不能为空', trigger: 'blur' }, { validator: validateWhiteList, trigger: 'blur' }, ], apiSchoolIds: [{ required: true, message: '学校不能为空', trigger: 'blur' }], phonenumber: [ { pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: '请输入正确的手机号码', trigger: 'blur', }, { required: true, message: '手机号不能为空', trigger: 'blur' }, ], }, userInfo: {}, dictSchool: [], schoolData: [], }) const { queryParams, form, rules, dictSchool, schoolData } = toRefs(data) // ========== 列配置 ========== const allColumns = ref([ { prop: 'userName', label: '用户名称', minWidth: '120', align: 'left', slot: true, }, { prop: 'nickName', label: '用户昵称', minWidth: '150', align: 'left', }, { prop: 'dept.deptName', label: '区域', align: 'center' }, { prop: 'userClass', label: '区域级别', align: 'center', slot: true }, { prop: 'status', label: '状态', align: 'center', slot: true, }, { prop: 'createTime', label: '创建时间', minWidth: '170', align: 'left', }, ]) // 👇 极简!只需一个空数组(或不初始化,但 Vue 推荐初始化) const selectedColumnProps = ref<string[]>([]) // visibleColumns 保持正确实现(按 selectedColumnProps 顺序映射) const visibleColumns = computed(() => { const columnMap = new Map(allColumns.value.map(col => [col.prop, col])) return selectedColumnProps.value.map(prop => columnMap.get(prop)).filter(Boolean) as Array<{ prop: string label: string slot?: boolean }> }) // ========== 方法 ========== function toggleExpand() { resetQuery() isExpanded.value = !isExpanded.value } function resetQueryParams() { queryParams.value.schoolId = null queryParams.value.cityId = null queryParams.value.districtId = null queryParams.value.provinceId = null } function setQueryParamsByType(dataType: string, id: number) { resetQueryParams() switch (dataType) { case 'shi': queryParams.value.cityId = id break case 'school': queryParams.value.districtId = id break case 'sheng': queryParams.value.provinceId = id break } } function handleNodeClick(data: any, node: any) { // 重置查询参数 resetQueryParams() // 此处可以根据点击节点的数据更新查询参数或其他业务逻辑 if (data.type == 'school') { // 如果是学校类型,设置学校ID queryParams.value.schoolId = data.id } else { setQueryParamsByType(data.queryType, data.id) } handleQuery() } function handleDefaultSelected(node: any) { if (node.type == 'school') { queryParams.value.schoolId = node.id } if (node.deptLabel === '1') { queryParams.value.cityId = node.id } if (node.deptLabel === '2') { queryParams.value.districtId = node.id } getList() } function handleQuery() { queryParams.value.pageNum = 1 getList() } function handleSelectionChange(selection: any[]) { selectedRows.value = selection ids.value = selection.map(item => item.id) single.value = selection.length != 1 multiple.value = !selection.length } function resetQuery() { // 重置表单(可根据需要扩展) dateRange.value = [] queryParams.value.classId = null proxy.resetForm('queryRef') queryParams.value.deptId = undefined proxy.$refs.deptTreeRef.setCurrentKey(null) handleQuery() } /** 通过条件过滤节点 */ const filterNode = (value, data) => { if (!value) return true return data.label.indexOf(value) !== -1 } /** 查询应用授权结构 */ function getSchool() { getListSys().then(response => { const res = proxy.handleTree(response.data, 'systemId') schoolData.value = res console.log(' schoolData.value==', schoolData.value) }) } let schoolMap = new Map() function searchAllSchool() { getSchoolDept({ parentId: '' }).then(response => { // console.log(response, "拿到的所有学校"); schoolAll.value = response.data for (let item of response.data) { schoolMap.set(item.schoolId, item) } schoolQy.value = response.data }) } /** 学校穿梭框change事件 */ const handleChange = (value, direction, movedKeys) => { form.value.schoolCodes = [] // 更新 schoolCodes 数组为对应的 schoolCode form.value.schoolCodes = value.map(id => schoolMap.get(id).schoolCode) console.log(form.value.schoolCodes, '当前数据') } searchAllSchool() /** 查询用户列表 */ function getList() { loading.value = true console.log(queryParams.value, 'queryParams.value') listUser(proxy.addDateRange(queryParams.value, dateRange.value)).then(res => { loading.value = false let rowsData = res.rows // for (let item of rowsData) { // item.userName = decryptDes(decrypt(item.userName)) // } userList.value = rowsData total.value = res.total }) } /** 查询部门下拉树结构 */ function getDeptTree() { deptTreeSelect().then(response => { deptOptions.value = response.data //defaultExpandedKeys.value = deptOptions.value.map(item => item.id) }) } /** 删除按钮操作 */ function handleDelete(row) { const userIds = row.userId || ids.value proxy.$modal .confirm('是否确认删除用户为"' + row.userName + '"的数据项?') .then(function () { return delUser(userIds) }) .then(() => { getList() proxy.$modal.msgSuccess('删除成功') }) .catch(() => {}) } /** 用户状态修改 */ function handleStatusChange(row) { console.log('运行了') let text = row.status === '0' ? '启用' : '停用' proxy.$modal .confirm('确认要"' + text + '""' + row.userName + '"用户吗?') .then(function () { return changeUserStatus(row.userId, row.status) }) .then(() => { proxy.$modal.msgSuccess(text + '成功') }) .catch(function () { row.status = row.status === '0' ? '1' : '0' }) } /** 重置密码按钮操作 */ function handleResetPwd(row) { proxy .$prompt('请输入新密码', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', closeOnClickModal: false, inputPattern: /^.{13,100}$/, inputErrorMessage: '用户密码长度必须至少 13 位', inputValidator: value => { if (/<|>|"|'|\||\\/.test(value)) { return '不能包含非法字符:< > " \' \\ |' } }, }) .then(({ value }) => { // let pass = ""; // if (value) { // const passName = encryptDes(value); // pass = encrypt(passName); // } resetUserPwd(row.userId, value).then(response => { proxy.$modal.msgSuccess('修改成功!') }) }) .catch(() => {}) } /** 下载模板操作 */ function importTemplate() { proxy.download('system/user/importTemplate', {}, `user_template_${new Date().getTime()}.xlsx`) } /**文件上传中处理 */ const handleFileUploadProgress = (event, file, fileList) => { upload.isUploading = true } /** 文件上传成功处理 */ const handleFileSuccess = (response, file, fileList) => { upload.open = false upload.isUploading = false proxy.$refs['uploadRef'].handleRemove(file) proxy.$alert( "<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + '</div>', '导入结果', { dangerouslyUseHTMLString: true }, ) getList() } /** 提交上传文件 */ function submitFileForm() { proxy.$refs['uploadRef'].submit() } /** 重置操作表单 */ function reset() { form.value = { userId: undefined, deptId: undefined, userName: undefined, nickName: undefined, password: undefined, phonenumber: undefined, email: undefined, sex: '2', status: '0', userClass: '5', whiteList: '', remark: undefined, postIds: [], roleIds: [], apiSchoolIds: [], schoolCodes: [], roleId: undefined, systemId: null, systemType: null, systemIds: null, } proxy.resetForm('userRef') } /** 弹窗关闭前 */ let transferRef = ref() function beforeCloseFun() { /** 清空穿梭框搜索条件 */ console.log(transferRef.value) transferRef.value.clearQuery('left') transferRef.value.clearQuery('right') open.value = false } /** 取消按钮 */ function cancel() { open.value = false reset() } /** 新增按钮操作 */ function handleAdd() { dictSchool.value = sys_user_school.value dictSchool.value.forEach(item => { item.disabled = true }) reset() open.value = true title.value = '添加用户' } /** 获取角色下拉 */ function getUserFun() { getUser().then(response => { postOptions.value = response.posts }) } /** 新角色下拉 */ function roleGetListFun() { roleGetList({ roleType: 2 }).then(res => { roleOptions.value = res.data }) } roleGetListFun() getUserFun() /** 修改按钮操作 */ function handleUpdate(row) { dictSchool.value = sys_user_school.value dictSchool.value.forEach(item => { item.disabled = true }) reset() const userId = row.userId || ids.value getUser(userId).then(response => { let resData = response.data /* 解密敏感信息 */ // if (resData.phonenumber) { // const desJm = decrypt(resData.phonenumber) // resData.phonenumber = decryptDes(desJm) // } // if (resData.userName) { // const desJm = decrypt(resData.userName) // resData.userName = decryptDes(desJm) // } // 处理 apiSchoolIds,转换为数组,并转换为数字 resData.apiSchoolIds = resData.apiSchoolIds ? resData.apiSchoolIds.split(',').map(Number) : [] /** 过滤无效的 schoolId */ resData.apiSchoolIds = resData.apiSchoolIds.filter(id => schoolMap.has(id)) /** 获取用户的 schoolCodes */ resData.schoolCodes = resData.apiSchoolIds.map(id => schoolMap.get(id).schoolCode) console.log('过滤后的 apiSchoolIds:', resData.apiSchoolIds) console.log('对应的 schoolCodes:', resData.schoolCodes) form.value = resData postOptions.value = response.posts form.value.postIds = response.postIds form.value.roleId = resData.roleId open.value = true title.value = '修改用户' form.password = '' }) } /** 提交按钮 */ function submitForm() { proxy.$refs['userRef'].validate(valid => { if (valid) { let formParam = JSON.parse(JSON.stringify(form.value)) console.log(formParam.apiSchoolIds, 'formParam.apiSchoolIds===?') console.log(formParam.schoolCodes, 'formParam.schoolCodes===?') if (formParam.apiSchoolIds != null) { formParam.apiSchoolIds = formParam.apiSchoolIds.join(',') } if (formParam.schoolCodes != null) { formParam.schoolCodes = formParam.schoolCodes.join(',') } // // if (formParam.userName) { // const desJmName = encryptDes(formParam.userName) // formParam.userName = encrypt(desJmName) // } // if (formParam.password) { // const passName = encryptDes(formParam.password); // formParam.password = encrypt(passName); // } if (formParam.userId != undefined) { if (Array.isArray(formParam.systemIds)) { formParam.systemIds = formParam.systemIds.join(',') } updateUser(formParam).then(response => { proxy.$modal.msgSuccess('修改成功') open.value = false getList() }) } else { addUser(formParam) .then(response => { console.log(response, '-1') if (response.code == 200) { proxy.$modal.msgSuccess('新增成功') open.value = false getList() } else { proxy.$modal.msgError(response.msg) } }) .catch(error => { // if (formParam.password) { // const passName = encryptDes(formParam.password); // form.value.password = encrypt(passName); // } }) } } }) } import { useDateRange } from '@/utils/disabled-date-range.hooks.js' // 禁用日期范围hooks const { disabledDateRange, calendarPanelsChange, clearDateRange, defaultTime, dateRangeShortcuts, disabledOverMonthCuts, } = useDateRange() // ========== 监听 ========== watch( selectedColumnProps, newVal => { // visibleColumns 是 computed,无需手动赋值 }, { immediate: true }, ) // ========== 生命周期 ========== onMounted(() => { // 可在此初始化树或触发首次查询 getDeptTree() getSchool() }) </script> <style lang="scss" scoped> .el-transfer { display: flex; width: 100%; } ::v-deep .el-transfer-panel { width: calc((100% - 70px) / 2) !important; } ::v-deep .el-transfer__buttons { display: flex; flex-direction: column; justify-content: center; align-items: center; flex-wrap: wrap; padding: 0; width: 69px; .el-button { width: 56px; padding: 0; margin: 10px 0; } } </style> 打开页面会出现弹窗,修改bug
最新发布
01-07
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值