From 01d423865ae5eddf91f35c8526f5683c3b430870 Mon Sep 17 00:00:00 2001 From: Crunchy <3114200645@qq.com> Date: 星期一, 13 一月 2025 09:30:06 +0800 Subject: [PATCH] 密码强校验添加 --- src/views/admin/user/index.vue | 768 ++++++++++++++++++++++++---------------------------------- 1 files changed, 319 insertions(+), 449 deletions(-) diff --git a/src/views/admin/user/index.vue b/src/views/admin/user/index.vue index d50b400..f99ad30 100644 --- a/src/views/admin/user/index.vue +++ b/src/views/admin/user/index.vue @@ -16,186 +16,69 @@ --> <template> - <div class="user"> - <basic-container> - <el-row :span="24"> - <el-col :xs="24" :sm="24" :md="5" class="user__tree"> - <avue-tree - :option="treeOption" - :data="treeData" - @node-click="nodeClick" - > + <div class="user"> + <basic-container> + <el-row :span="24"> + <el-col :xs="24" :sm="24" :md="5" class="user__tree"> + <avue-tree :option="treeOption" :data="treeData" @node-click="nodeClick"> <span class="el-tree-node__label" slot-scope="{ node, data }"> - <el-tooltip - class="item" - effect="dark" - content="鏃犳暟鎹潈闄�" - placement="right-start" - v-if="data.isLock" - > + <el-tooltip class="item" effect="dark" content="鏃犳暟鎹潈闄�" placement="right-start" v-if="data.isLock"> <span>{{ node.label }} <i class="el-icon-lock"></i></span> </el-tooltip> <span v-if="!data.isLock">{{ node.label }}</span> </span> - </avue-tree> - </el-col> - <el-col :xs="24" :sm="24" :md="19" class="user__main"> - <avue-crud - ref="crud" - :option="option" - v-model="form" - :page="page" - :table-loading="listLoading" - :before-open="handleOpenBefore" - :data="list" - @on-load="getList" - @search-change="searchChange" - @refresh-change="refreshChange" - @size-change="sizeChange" - @current-change="currentChange" - @row-update="update" - @row-save="create" - > - <template slot="menuLeft"> - <el-button - v-if="sys_user_add" - class="filter-item" - type="primary" - size="small" - icon="el-icon-edit" - @click="$refs.crud.rowAdd()" - >娣诲姞 - </el-button> - <!-- <el-button - v-if="sys_user_add" - class="filter-item" - type="primary" - size="small" - icon="el-icon-upload" - @click="importDialogVisible=true" - >瀵煎叆 - </el-button> --> - </template> - <template slot="username" slot-scope="scope"> - <span>{{ scope.row.username }}</span> - </template> - <template slot="role" slot-scope="scope"> + </avue-tree> + </el-col> + <el-col :xs="24" :sm="24" :md="19" class="user__main"> + <avue-crud ref="crud" :option="option" v-model="form" :page="page" :table-loading="listLoading" :before-open="handleOpenBefore" :data="list" @on-load="getList" @search-change="searchChange" @refresh-change="refreshChange" @size-change="sizeChange" @current-change="currentChange" @row-update="update" @row-save="create"> + <template slot="menuLeft"> + <el-button v-if="sys_user_add" class="filter-item" type="primary" size="small" icon="el-icon-edit" @click="$refs.crud.rowAdd()">娣诲姞 </el-button> + </template> + <template slot="username" slot-scope="scope"> + <span>{{ scope.row.username }}</span> + </template> + <template slot="role" slot-scope="scope"> <span v-for="(role, index) in scope.row.roleList" :key="index"> <el-tag>{{ role.roleName }} </el-tag> </span> - </template> - <template slot="deptId" slot-scope="scope"> - {{ scope.row.deptName }} - </template> - <template slot="lockFlag" slot-scope="scope"> - <el-tag>{{ scope.label }}</el-tag> - </template> - <template slot="menu" slot-scope="scope"> - <el-button - v-if="sys_user_edit" - type="text" - size="small" - icon="el-icon-edit" - @click="handleUpdate(scope.row, scope.index)" - >缂栬緫 - </el-button> - <el-button - v-if="sys_user_del" - type="text" - size="small" - icon="el-icon-delete" - @click="deletes(scope.row, scope.index)" - >鍒犻櫎 - </el-button> - <el-button - v-if="sys_user_lock" - type="text" - size="small" - icon="el-icon-unlock" - @click="unlock(scope.row, scope.index)" - >瑙i攣 - </el-button> - </template> - <template slot="deptIdForm" slot-scope="scope"> - <avue-input-tree - v-model="form.deptId" - :node-click="getNodeData" - :dic="treeDeptData" - :props="defaultProps" - placeholder="璇烽�夋嫨鎵�灞炲垎缁�" - /> - </template> - <template slot="staffInfoForm" slot-scope="scope"> - <el-input - @focus="showStaff = true" - v-model="form.staffInfo" - readonly - > - <i - class="el-icon-arrow-down el-input__icon" - slot="suffix" - @click="showStaff = true" - ></i> - </el-input> - </template> - <template slot="roleForm" slot-scope="scope"> - <avue-select - v-model="role" - :dic="rolesOptions" - :props="roleProps" - multiple - placeholder="璇烽�夋嫨瑙掕壊" - /> - </template> - </avue-crud> - </el-col> - </el-row> - </basic-container> + </template> + <template slot="deptId" slot-scope="scope"> + {{ scope.row.deptName }} + </template> + <template slot="lockFlag" slot-scope="scope"> + <el-tag>{{ scope.label }}</el-tag> + </template> + <template slot="menu" slot-scope="scope"> + <el-button v-if="sys_user_edit" type="text" size="small" icon="el-icon-edit" @click="handleUpdate(scope.row, scope.index)">缂栬緫 </el-button> + <el-button v-if="sys_user_del" type="text" size="small" icon="el-icon-delete" @click="deletes(scope.row, scope.index)">鍒犻櫎 </el-button> + <el-button v-if="sys_user_lock" type="text" size="small" icon="el-icon-unlock" @click="unlock(scope.row, scope.index)">瑙i攣 </el-button> + </template> + <template slot="deptIdForm" slot-scope="scope"> + <avue-input-tree v-model="form.deptId" :node-click="getNodeData" :dic="treeDeptData" :props="defaultProps" placeholder="璇烽�夋嫨鎵�灞炲垎缁�" /> + </template> + <template slot="staffInfoForm" slot-scope="scope"> + <el-input @focus="showStaff = true" v-model="form.staffInfo" readonly> + <i class="el-icon-arrow-down el-input__icon" slot="suffix" @click="showStaff = true"></i> + </el-input> + </template> + <template slot="roleForm" slot-scope="scope"> + <avue-select v-model="role" :dic="rolesOptions" :props="roleProps" multiple placeholder="璇烽�夋嫨瑙掕壊" /> + </template> + <template slot="passwordForm" slot-scope="scope"> + <div class="password-input-container"> + <el-input v-model="form.password" type="password" @input="checkPasswordStrength" placeholder="璇疯緭鍏ュ瘑鐮�" show-password style="width: 100%"> </el-input> + <div v-if="form.password" class="password-strength-indicator"> + 瀵嗙爜寮哄害: <span :class="passwordLevelClass">{{ passwordLevel }}</span> + </div> + </div> + </template> + </avue-crud> + </el-col> + </el-row> + </basic-container> - <staffDialog - :currshowlist.sync="showStaff" - @listenToStaffEvent="selectStaff" - /> - <el-dialog title="瀵煎叆" :visible.sync="importDialogVisible" width="30%"> - <span> - <div> - <div> - <el-upload - style="margin-left:8px;display: inline;" - class="upload-demo" - drag - :headers="headers" - :action="uploadInfo.url" - :beforeUpload="beforeAvatarUpload" - :limit="1" - :show-file-list="false" - :file-list="fileList" - :on-success="fileSuccessUploadScan" - :on-error="handleError" - accept=".xlsx,.xls,.csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" - :auto-upload="true" - ref="uploadScan" - multiple - > - <i class="el-icon-upload"></i> - <div class="el-upload__text"><em>鐐瑰嚮瀵煎叆鏁版嵁</em></div> - <div class="el-upload__tip" slot="tip" > - 鍙兘涓婁紶xlsx/xls鏂囦欢锛屼笖涓嶈秴杩�10M<el-button - type="text" - style="font-size:12px;" - @click="downDataTemplate(uploadInfo.fileName)" - v-if="uploadInfo.Download" - >涓嬭浇妯℃澘</el-button - > - </div> - </el-upload> - </div> - <div></div> - </div> - </span> - <span slot="footer" class="dialog-footer"> </span> - </el-dialog> - </div> + <staffDialog :currshowlist.sync="showStaff" @listenToStaffEvent="selectStaff" /> + </div> </template> <script> import staffDialog from '@/views/common/staff.vue' @@ -206,298 +89,285 @@ import { mapGetters } from 'vuex' import Template from '../../quality/parts/template' import { getObj } from '@/api/basic/staff' -import { getStore } from '@/util/store.js' -import { uploadTemplate } from '@/api/basic/template' + export default { - name: 'SysUser', - components: { Template, staffDialog }, - data() { - return { - fileList: [], // 涓婁紶鏂囦欢鍒楄〃 - // 涓婁紶澶翠俊鎭� - headers: { - Authorization: 'Bearer ' + getStore({ name: 'access_token' }) - }, - uploadInfo: { - // 鏄惁灞曠ず涓婁紶EXCEL浠ュ強瀵瑰簲鐨剈rl - isShow: true, - url: '/mes/user/upload', - download: true, - fileName: '鐢ㄦ埛妯℃澘' - }, - importDialogVisible: false, - showStaff: false, - searchForm: {}, - treeOption: { - nodeKey: 'id', - addBtn: false, - menu: false, - props: { - label: 'name', - value: 'id' + name: 'SysUser', + components: { Template, staffDialog }, + data() { + return { + showStaff: false, + searchForm: {}, + treeOption: { + nodeKey: 'id', + addBtn: false, + menu: false, + props: { + label: 'name', + value: 'id' + } + }, + treeData: [], + option: tableOption, + treeDeptData: [], + checkedKeys: [], + roleProps: { + label: 'roleName', + value: 'roleId' + }, + defaultProps: { + label: 'name', + value: 'id' + }, + page: { + total: 0, // 鎬婚〉鏁� + currentPage: 1, // 褰撳墠椤垫暟 + pageSize: 20, // 姣忛〉鏄剧ず澶氬皯鏉�, + isAsc: false // 鏄惁鍊掑簭 + }, + list: [], + listLoading: true, + role: [], + form: {}, + rolesOptions: [], + passwordLevel: '', // 瀵嗙爜寮哄害绾у埆 + passwordLevelClass: '' // 瀵嗙爜寮哄害鏍峰紡绫� } - }, - treeData: [], - option: tableOption, - treeDeptData: [], - checkedKeys: [], - roleProps: { - label: 'roleName', - value: 'roleId' - }, - defaultProps: { - label: 'name', - value: 'id' - }, - page: { - total: 0, // 鎬婚〉鏁� - currentPage: 1, // 褰撳墠椤垫暟 - pageSize: 20, // 姣忛〉鏄剧ず澶氬皯鏉�, - isAsc: false // 鏄惁鍊掑簭 - }, - list: [], - listLoading: true, - role: [], - form: {}, - rolesOptions: [] - } - }, - computed: { - ...mapGetters(['permissions']) - }, - watch: { - role() { - this.form.role = this.role - } - }, - created() { - this.sys_user_add = this.permissions.sys_user_add - this.sys_user_edit = this.permissions.sys_user_edit - this.sys_user_del = this.permissions.sys_user_del - this.sys_user_lock = this.permissions.sys_user_lock - this.init() - }, - methods: { - // 闄愬埗鏂囦欢涓婁紶澶у皬锛岀洰鍓嶉檺鍒朵负10M锛堝彟鍙互鍔犵被鍨嬮檺鍒讹級 - beforeAvatarUpload(file) { - const fileName = file.name - const fileType = fileName.substring(fileName.lastIndexOf('.') + 1) - const isLt10M = file.size / 1024 / 1024 < 10 - if (fileType !== 'xlsx' && fileType !== 'xls') { - this.$message.error('鏂囦欢鏍煎紡鍙兘涓簒lsx鎴杧ls,璇峰垹闄ゅ悗閲嶆柊涓婁紶') - } - if (!isLt10M) { - this.$message({ - message: '鏂囦欢澶у皬', - type: 'warning' - }) - } - return isLt10M }, - // 鏂囦欢涓婁紶鎴愬姛鍥炶皟浜嬩欢 - fileSuccessUploadScan(response, file, fileList) { - if (response.code != '0') { - this.$message.warning(response.msg) - } else { - if(response.data!=""&&response.data!=[]&&response.data!=null){ - this.$message({ - message: response.data, - type: 'success', - dangerouslyUseHTMLString: true, - }) - }else{ - this.$message({ - message: '涓婁紶鎴愬姛', - type: 'success' - }) - } - this.importDialogVisible=false - this.fileList=[] + computed: { + ...mapGetters(['permissions']) + }, + watch: { + role() { + this.form.role = this.role + } + }, + created() { + this.sys_user_add = this.permissions.sys_user_add + this.sys_user_edit = this.permissions.sys_user_edit + this.sys_user_del = this.permissions.sys_user_del + this.sys_user_lock = this.permissions.sys_user_lock this.init() - // this.getDataList() - } - this.$refs.uploadScan.clearFiles() }, - // 涓婁紶澶辫触 - handleError(err, file, fileList) { - const error = JSON.parse(err.message) - if (error.msg) { - this.$message.error(error.msg) - } else { - this.$message.error('涓婁紶澶辫触') - } - }, - // 涓嬭浇鏁版嵁妯℃澘 - downDataTemplate() { - uploadTemplate("user").then((response) => { - const blob = new Blob([response.data], { - type: 'application/force-download' - }) - let fileName="妯℃澘鏂囦欢"; - if(this.uploadInfo.fileName!=undefined&&this.uploadInfo.fileName!=''&&this.uploadInfo.fileName!=null){ - fileName=this.uploadInfo.fileName - } - const filename = decodeURI(fileName+'.xlsx') - // 鍒涘缓涓�涓秴閾炬帴锛屽皢鏂囦欢娴佽祴杩涘幓锛岀劧鍚庡疄鐜拌繖涓秴閾炬帴鐨勫崟鍑讳簨浠� - const elink = document.createElement('a') - elink.download = filename - elink.style.display = 'none' - elink.href = URL.createObjectURL(blob) - document.body.appendChild(elink) - elink.click() - URL.revokeObjectURL(elink.href) // 閲婃斁URL 瀵硅薄 - document.body.removeChild(elink) - }) - }, - selectStaff(staff) { - this.form.staffInfo = staff.staffName + '-' + staff.staffNo - this.form.phone = staff.phone - this.form.staffId = staff.id - }, - init() { - fetchTree().then((response) => { - this.treeData = response.data.data - }) - }, - nodeClick(data) { - this.page.page = 1 - this.getList(this.page, { deptId: data.id }) - }, - getList(page, params) { - this.listLoading = true - fetchList( - Object.assign( - { - current: page.currentPage, - size: page.pageSize - }, - params, - this.searchForm - ) - ).then((response) => { - this.list = response.data.data.records - this.page.total = response.data.data.total - this.listLoading = false - }) - }, - getNodeData() { - deptRoleList().then((response) => { - this.rolesOptions = response.data.data - }) - }, - searchChange(param, done) { - this.searchForm = param - this.page.currentPage = 1 - this.getList(this.page, param) - done() - }, - sizeChange(pageSize) { - this.page.pageSize = pageSize - }, - currentChange(current) { - this.page.currentPage = current - }, - refreshChange() { - this.getList(this.page) - }, - handleOpenBefore(show, type) { - window.boxType = type - // 鏌ヨ閮ㄩ棬鏍� - fetchTree().then((response) => { - this.treeDeptData = response.data.data - }) - // 鏌ヨ瑙掕壊鍒楄〃 - deptRoleList().then((response) => { - this.rolesOptions = response.data.data - }) + methods: { + selectStaff(staff) { + this.form.staffInfo = staff.staffName + '-' + staff.staffNo + this.form.phone = staff.phone + this.form.staffId = staff.id + }, + init() { + fetchTree().then((response) => { + this.treeData = response.data.data + }) + }, + nodeClick(data) { + this.page.page = 1 + this.getList(this.page, { deptId: data.id }) + }, + getList(page, params) { + this.listLoading = true + fetchList( + Object.assign( + { + current: page.currentPage, + size: page.pageSize + }, + params, + this.searchForm + ) + ).then((response) => { + this.list = response.data.data.records + this.page.total = response.data.data.total + this.listLoading = false + }) + }, + getNodeData() { + deptRoleList().then((response) => { + this.rolesOptions = response.data.data + }) + }, + searchChange(param, done) { + this.searchForm = param + this.page.currentPage = 1 + this.getList(this.page, param) + done() + }, + sizeChange(pageSize) { + this.page.pageSize = pageSize + }, + currentChange(current) { + this.page.currentPage = current + }, + refreshChange() { + this.getList(this.page) + }, + handleOpenBefore(show, type) { + window.boxType = type + // 鏌ヨ閮ㄩ棬鏍� + fetchTree().then((response) => { + this.treeDeptData = response.data.data + }) + // 鏌ヨ瑙掕壊鍒楄〃 + deptRoleList().then((response) => { + this.rolesOptions = response.data.data + }) - if (['edit', 'views'].includes(type)) { - this.role = [] - for (let i = 0; i < this.form.roleList.length; i++) { - this.role[i] = this.form.roleList[i].roleId - } - } else if (type === 'add') { - this.role = [] - } - show() - }, - handleUpdate(row, index) { - this.$refs.crud.rowEdit(row, index) - this.form.password = undefined - }, + if (['edit', 'views'].includes(type)) { + this.role = [] + for (let i = 0; i < this.form.roleList.length; i++) { + this.role[i] = this.form.roleList[i].roleId + } + } else if (type === 'add') { + this.role = [] + } + show() + }, + handleUpdate(row, index) { + this.$refs.crud.rowEdit(row, index) + this.form.password = undefined + }, - create(row, done, loading) { - if (this.form.phone.indexOf('*') > 0) { - this.form.phone = undefined - } - addObj(this.form) - .then(() => { - this.getList(this.page) - done() - this.$notify.success('鍒涘缓鎴愬姛') - }) - .catch(() => { - loading() - }) - }, - update(row, index, done, loading) { - if (this.form.phone && this.form.phone.indexOf('*') > 0) { - this.form.phone = undefined - } - putObj(this.form) - .then(() => { - this.getList(this.page) - done() - this.$notify.success('淇敼鎴愬姛') - }) - .catch(() => { - loading() - }) - }, - deletes(row, index) { - this.$confirm( - '姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ョ敤鎴�(鐢ㄦ埛鍚�:' + row.username + '), 鏄惁缁х画?', - '鎻愮ず', - { - confirmButtonText: '纭畾', - cancelButtonText: '鍙栨秷', - closeOnClickModal: false, - type: 'warning' + create(row, done, loading) { + // 妫�鏌ュ瘑鐮佸己搴� + if (this.passwordLevel !== '寮�') { + this.$message.warning('瀵嗙爜寮哄害涓嶅锛岃纭繚瀵嗙爜鍖呭惈锛氬ぇ灏忓啓瀛楁瘝銆佹暟瀛楀拰鐗规畩瀛楃锛屼笖闀垮害涓嶅皯浜�8浣�') + loading() + return + } + + if (this.form.phone.indexOf('*') > 0) { + this.form.phone = undefined + } + + addObj(this.form) + .then(() => { + this.getList(this.page) + done() + this.$notify.success('鍒涘缓鎴愬姛') + }) + .catch(() => { + loading() + }) + }, + update(row, index, done, loading) { + // 濡傛灉淇敼浜嗗瘑鐮侊紝涔熻妫�鏌ュ瘑鐮佸己搴� + if (this.form.password && this.passwordLevel !== '寮�') { + this.$message.warning('瀵嗙爜寮哄害涓嶅锛岃纭繚瀵嗙爜鍖呭惈锛氬ぇ灏忓啓瀛楁瘝銆佹暟瀛楀拰鐗规畩瀛楃锛屼笖闀垮害涓嶅皯浜�8浣�') + loading() + return + } + + if (this.form.phone && this.form.phone.indexOf('*') > 0) { + this.form.phone = undefined + } + + putObj(this.form) + .then(() => { + this.getList(this.page) + done() + this.$notify.success('淇敼鎴愬姛') + }) + .catch(() => { + loading() + }) + }, + deletes(row, index) { + this.$confirm('姝ゆ搷浣滃皢姘镐箙鍒犻櫎璇ョ敤鎴�(鐢ㄦ埛鍚�:' + row.username + '), 鏄惁缁х画?', '鎻愮ず', { + confirmButtonText: '纭畾', + cancelButtonText: '鍙栨秷', + closeOnClickModal: false, + type: 'warning' + }).then(() => { + delObj(row.userId) + .then(() => { + this.list.splice(index, 1) + this.$notify.success('鍒犻櫎鎴愬姛') + }) + .catch(() => { + this.$notify.error('鍒犻櫎澶辫触') + }) + }) + }, + unlock(row, index) { + unlock({ id: row.userId }).then((repsonse) => {}) + }, + // 妫�鏌ュ瘑鐮佸己搴� + checkPasswordStrength(password) { + let strength = 0 + + // 妫�鏌ラ暱搴� + if (password.length >= 8) strength++ + + // 妫�鏌ユ槸鍚﹀寘鍚暟瀛� + if (/\d/.test(password)) strength++ + + // 妫�鏌ユ槸鍚﹀寘鍚皬鍐欏瓧姣� + if (/[a-z]/.test(password)) strength++ + + // 妫�鏌ユ槸鍚﹀寘鍚ぇ鍐欏瓧姣� + if (/[A-Z]/.test(password)) strength++ + + // 妫�鏌ユ槸鍚﹀寘鍚壒娈婂瓧绗� + if (/[!@#$%^&*]/.test(password)) strength++ + + switch (strength) { + case 0: + case 1: + this.passwordLevel = '寮�' + this.passwordLevelClass = 'password-weak' + break + case 2: + case 3: + this.passwordLevel = '涓�' + this.passwordLevelClass = 'password-medium' + break + case 4: + case 5: + this.passwordLevel = '寮�' + this.passwordLevelClass = 'password-strong' + break + } } - ).then(() => { - delObj(row.userId) - .then(() => { - this.list.splice(index, 1) - this.$notify.success('鍒犻櫎鎴愬姛') - }) - .catch(() => { - this.$notify.error('鍒犻櫎澶辫触') - }) - }) - }, - unlock(row, index) { - unlock({ id: row.userId }).then((repsonse) => { - if(repsonse.data.data){ - this.$message.success("璇ョ敤鎴峰凡瑙i攣") - } - }) } - } } </script> <style lang="scss"> .user { - height: 100%; + height: 100%; - &__tree { - padding-top: 3px; - padding-right: 20px; - } - - &__main { - .el-card__body { - padding-top: 0; + &__tree { + padding-top: 3px; + padding-right: 20px; } - } + + &__main { + .el-card__body { + padding-top: 0; + } + } +} + +.password-input-container { + width: 100%; + .el-input { + width: 100%; + } +} + +.password-strength-indicator { + margin-top: 5px; + font-size: 12px; + color: #606266; +} + +.password-weak { + color: #f56c6c; +} + +.password-medium { + color: #e6a23c; +} + +.password-strong { + color: #67c23a; } </style> -- Gitblit v1.9.3