#
Junjie
3 天以前 bd6b518aae61608ddc2d82b43ccc283dc95b9c54
src/main/webapp/views/user/user.html
@@ -1,177 +1,429 @@
<!DOCTYPE html>
<html lang="en">
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <title></title>
    <meta charset="UTF-8">
    <title>系统用户</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all">
    <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all">
    <link rel="stylesheet" href="../../static/css/cool.css" media="all">
    <link rel="stylesheet" href="../../static/css/originTable.css" media="all">
    <link rel="stylesheet" href="../../static/vue/element/element.css">
    <link rel="stylesheet" href="../../static/css/cool.css">
    <style>
        body {
            color: #595959;
            background-color: #f5f7f9;
        :root {
            --card-bg: rgba(255, 255, 255, 0.96);
            --card-border: rgba(217, 227, 238, 0.96);
            --text-main: #243447;
            --text-sub: #6d7f90;
        }
        .admin-form {
            padding: 25px 30px 0 0 !important;
            margin: 0 !important;
        [v-cloak] {
            display: none;
        }
        html,
        body {
            margin: 0;
            min-height: 100%;
            color: var(--text-main);
            font-family: "Avenir Next", "PingFang SC", "Microsoft YaHei", sans-serif;
            background:
                radial-gradient(920px 360px at 0% 0%, rgba(48, 112, 196, 0.10), transparent 58%),
                radial-gradient(760px 280px at 100% 10%, rgba(25, 160, 138, 0.08), transparent 60%),
                linear-gradient(180deg, #f3f7fb 0%, #f8fafc 100%);
        }
        .page-shell {
            padding: 14px;
            box-sizing: border-box;
        }
        .card-shell {
            max-width: 1600px;
            margin: 0 auto;
            border-radius: 22px;
            border: 1px solid var(--card-border);
            background:
                radial-gradient(780px 220px at -8% 0%, rgba(45, 118, 196, 0.05), transparent 58%),
                radial-gradient(640px 180px at 106% 16%, rgba(24, 150, 129, 0.05), transparent 56%),
                var(--card-bg);
            box-shadow: 0 16px 32px rgba(44, 67, 96, 0.08);
            overflow: hidden;
        }
        .card-head {
            padding: 16px 18px 14px;
            border-bottom: 1px solid rgba(223, 231, 240, 0.92);
        }
        .head-top {
            display: flex;
            align-items: flex-start;
            justify-content: space-between;
            gap: 16px;
            flex-wrap: wrap;
            margin-bottom: 12px;
        }
        .head-title {
            display: flex;
            flex-direction: column;
            gap: 6px;
        }
        .head-title h1 {
            margin: 0;
            font-size: 20px;
            line-height: 1.2;
        }
        .head-title p {
            margin: 0;
            font-size: 13px;
            line-height: 1.6;
            color: var(--text-sub);
        }
        .head-actions {
            display: flex;
            gap: 10px;
            flex-wrap: wrap;
        }
        .head-actions .el-button {
            min-width: 96px;
        }
        .search-form {
            display: flex;
            align-items: center;
            gap: 8px 12px;
            flex-wrap: wrap;
        }
        .search-form .el-form-item {
            margin-bottom: 0;
        }
        .search-form .el-form-item__label {
            font-weight: 600;
            color: #55697d;
        }
        .search-form .el-input__inner,
        .search-form .el-button {
            height: 34px;
            line-height: 34px;
        }
        .table-wrap {
            padding: 12px 18px 16px;
        }
        .table-shell {
            border-radius: 18px;
            overflow: hidden;
            border: 1px solid rgba(217, 227, 238, 0.98);
            background: rgba(255, 255, 255, 0.95);
        }
        .table-shell .el-table th {
            background: #f7fafc;
            color: #53677d;
            font-weight: 700;
        }
        .table-shell .el-table td,
        .table-shell .el-table th {
            padding: 10px 0;
        }
        .status-switch {
            display: inline-flex;
            align-items: center;
        }
        .pager-bar {
            padding: 16px 0 0;
            display: flex;
            justify-content: flex-end;
        }
        .dialog-panel .el-dialog {
            border-radius: 22px;
            overflow: hidden;
        }
        .dialog-panel .el-dialog__header {
            padding: 20px 22px 12px;
            background: linear-gradient(180deg, #f8fbff 0%, #f3f7fb 100%);
            border-bottom: 1px solid rgba(224, 232, 241, 0.92);
        }
        .dialog-panel .el-dialog__title {
            font-weight: 700;
            color: var(--text-main);
        }
        .dialog-panel .el-dialog__body {
            padding: 20px 22px 8px;
        }
        .dialog-form .el-form-item {
            margin-bottom: 16px;
        }
        .dialog-form .el-form-item__label {
            font-weight: 600;
            color: #5b6f83;
        }
        .dialog-form .el-input__inner,
        .dialog-form .el-select .el-input__inner {
            height: 36px;
            line-height: 36px;
        }
        .dialog-tip {
            margin: 4px 0 2px;
            padding: 10px 12px;
            border-radius: 12px;
            font-size: 12px;
            line-height: 1.6;
            color: #748497;
            background: rgba(248, 251, 255, 0.92);
            border: 1px solid rgba(226, 233, 242, 0.96);
        }
        .dialog-footer {
            display: flex;
            justify-content: flex-end;
            gap: 10px;
        }
        .reset-user {
            margin-bottom: 16px;
            padding: 12px 14px;
            border-radius: 12px;
            background: rgba(248, 251, 255, 0.92);
            border: 1px solid rgba(226, 233, 242, 0.96);
            color: var(--text-sub);
            font-size: 13px;
        }
        .table-action-danger {
            color: #f56c6c;
        }
        @media (max-width: 768px) {
            .page-shell {
                padding: 10px;
            }
            .card-head,
            .table-wrap {
                padding-left: 12px;
                padding-right: 12px;
            }
            .dialog-panel .el-dialog {
                width: calc(100% - 24px) !important;
            }
        }
    </style>
</head>
<body>
<!-- 正文开始 -->
<div class="layui-fluid" style="padding-bottom: 0;">
    <div class="layui-row layui-col-space15">
        <div class="layui-col-md12">
            <div class="layui-card">
                <div class="layui-card-body" style="padding: 10px;">
                    <form class="layui-form toolbar">
                        <div class="layui-form-item">
                            <div class="layui-inline">
                                <label class="layui-form-label">用户名:</label>
                                <div class="layui-input-inline">
                                    <input name="username" class="layui-input" placeholder="输入用户名"/>
                                </div>
                            </div>
                            <div class="layui-inline">
                                <label class="layui-form-label">手机号:</label>
                                <div class="layui-input-inline">
                                    <input name="mobile" class="layui-input" placeholder="输入手机号"/>
                                </div>
                            </div>
                            <div class="layui-inline">&emsp;
                                <button class="layui-btn icon-btn" lay-filter="userTbSearch" lay-submit>
                                    <i class="layui-icon">&#xe615;</i>搜索
                                </button>
                            </div>
                        </div>
                    </form>
                    <table id="userTable" lay-filter="userTable"></table>
<div id="app" v-cloak class="page-shell">
    <div class="card-shell">
        <div class="card-head">
            <div class="head-top">
                <div class="head-title">
                    <h1>系统用户</h1>
                    <p>修改界面不再显示密码,密码调整统一通过“重置密码”完成;角色、状态等字段恢复为选择控件。</p>
                </div>
                <div class="head-actions">
                    <el-button type="primary" icon="el-icon-plus" @click="openCreateDialog">新增用户</el-button>
                    <el-button type="danger" icon="el-icon-delete" :disabled="selection.length === 0" @click="removeSelection">删除所选</el-button>
                </div>
            </div>
            <el-form :inline="true" :model="searchForm" class="search-form" @submit.native.prevent>
                <el-form-item label="登录账户">
                    <el-input v-model.trim="searchForm.username" clearable placeholder="请输入登录账户" @keyup.enter.native="handleSearch"></el-input>
                </el-form-item>
                <el-form-item label="账号">
                    <el-input v-model.trim="searchForm.mobile" clearable placeholder="请输入账号" @keyup.enter.native="handleSearch"></el-input>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary" icon="el-icon-search" @click="handleSearch">查询</el-button>
                    <el-button icon="el-icon-refresh-left" @click="handleResetSearch">重置</el-button>
                </el-form-item>
            </el-form>
        </div>
        <div class="table-wrap">
            <div class="table-shell" v-loading="loading">
                <el-table
                    :data="tableData"
                    border
                    stripe
                    height="calc(100vh - 245px)"
                    @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="48" align="center"></el-table-column>
                    <el-table-column prop="username" label="登录账户" min-width="150" show-overflow-tooltip></el-table-column>
                    <el-table-column prop="mobile" label="账号" min-width="150" show-overflow-tooltip></el-table-column>
                    <el-table-column prop="roleName" label="角色" min-width="150" show-overflow-tooltip></el-table-column>
                    <el-table-column label="MFA授权" width="110" align="center">
                        <template slot-scope="scope">
                            <el-tag size="mini" :type="Number(scope.row.mfaAllow) === 1 ? 'success' : 'info'">
                                {{ Number(scope.row.mfaAllow) === 1 ? '已授权' : '未授权' }}
                            </el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column label="MFA状态" width="110" align="center">
                        <template slot-scope="scope">
                            <el-tag size="mini" :type="Number(scope.row.mfaEnabled) === 1 ? 'success' : 'warning'">
                                {{ Number(scope.row.mfaEnabled) === 1 ? '已启用' : '未启用' }}
                            </el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column label="状态" width="130" align="center">
                        <template slot-scope="scope">
                            <div class="status-switch">
                                <el-switch
                                    v-model="scope.row.status"
                                    :active-value="1"
                                    :inactive-value="0"
                                    active-text="正常"
                                    inactive-text="禁用"
                                    @change="toggleStatus(scope.row)">
                                </el-switch>
                            </div>
                        </template>
                    </el-table-column>
                    <el-table-column label="操作" width="220" fixed="right" align="center">
                        <template slot-scope="scope">
                            <el-button type="text" @click="openEditDialog(scope.row)">编辑</el-button>
                            <el-button type="text" @click="openResetPasswordDialog(scope.row)">重置密码</el-button>
                            <el-button type="text" class="table-action-danger" @click="removeRows([scope.row.id])">删除</el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </div>
            <div class="pager-bar">
                <el-pagination
                    background
                    layout="total, sizes, prev, pager, next, jumper"
                    :current-page="page.curr"
                    :page-size="page.limit"
                    :page-sizes="[15, 30, 50, 100, 200, 500]"
                    :total="page.total"
                    @size-change="handleSizeChange"
                    @current-change="handleCurrentChange">
                </el-pagination>
            </div>
        </div>
    </div>
    <el-dialog
        class="dialog-panel"
        :title="dialog.mode === 'create' ? '新增用户' : '修改用户'"
        :visible.sync="dialog.visible"
        width="620px"
        :close-on-click-modal="false"
        append-to-body>
        <el-form
            ref="dialogForm"
            :model="dialogForm"
            :rules="dialogRules"
            label-width="88px"
            class="dialog-form"
            @submit.native.prevent>
            <el-row :gutter="18">
                <el-col :xs="24" :sm="12">
                    <el-form-item label="登录账户" prop="username">
                        <el-input v-model.trim="dialogForm.username" maxlength="32" placeholder="请输入登录账户"></el-input>
                    </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="12">
                    <el-form-item label="账号" prop="mobile">
                        <el-input v-model.trim="dialogForm.mobile" maxlength="32" placeholder="请输入账号"></el-input>
                    </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="12">
                    <el-form-item label="角色" prop="roleId">
                        <el-select v-model="dialogForm.roleId" placeholder="请选择角色" style="width: 100%;">
                            <el-option
                                v-for="role in roles"
                                :key="role.id"
                                :label="role.name"
                                :value="Number(role.id)">
                            </el-option>
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="12">
                    <el-form-item label="状态">
                        <el-select v-model="dialogForm.status" placeholder="请选择状态" style="width: 100%;">
                            <el-option label="正常" :value="1"></el-option>
                            <el-option label="禁用" :value="0"></el-option>
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :xs="24" :sm="12">
                    <el-form-item label="MFA授权">
                        <el-select v-model="dialogForm.mfaAllow" placeholder="请选择" style="width: 100%;">
                            <el-option label="不允许" :value="0"></el-option>
                            <el-option label="允许" :value="1"></el-option>
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col v-if="dialog.mode === 'create'" :xs="24" :sm="12">
                    <el-form-item label="初始密码" prop="password">
                        <el-input v-model.trim="dialogForm.password" show-password maxlength="32" placeholder="请输入初始密码"></el-input>
                    </el-form-item>
                </el-col>
            </el-row>
            <div v-if="dialog.mode === 'edit'" class="dialog-tip">
                修改界面不显示密码。如需调整密码,请关闭当前窗口后使用列表里的“重置密码”。
            </div>
        </el-form>
        <span slot="footer" class="dialog-footer">
            <el-button @click="closeDialog">取消</el-button>
            <el-button type="primary" :loading="dialogSubmitting" @click="submitDialog">保存</el-button>
        </span>
    </el-dialog>
    <el-dialog
        class="dialog-panel"
        title="重置密码"
        :visible.sync="resetDialog.visible"
        width="420px"
        :close-on-click-modal="false"
        append-to-body>
        <div class="reset-user">当前用户:{{ resetDialog.username || '--' }}</div>
        <el-form
            ref="resetForm"
            :model="resetDialog"
            :rules="resetRules"
            label-width="72px"
            class="dialog-form"
            @submit.native.prevent>
            <el-form-item label="新密码" prop="password">
                <el-input v-model.trim="resetDialog.password" show-password maxlength="32" placeholder="请输入新密码"></el-input>
            </el-form-item>
        </el-form>
        <span slot="footer" class="dialog-footer">
            <el-button @click="closeResetDialog">取消</el-button>
            <el-button type="primary" :loading="resetSubmitting" @click="submitResetPassword">确定</el-button>
        </span>
    </el-dialog>
</div>
<script type="text/html" id="hostTpl">
    <span name="hostName" class="layui-badge layui-badge-gray">{{d.hostName}}</span>
</script>
<script type="text/html" id="statusTpl">
    <input type="checkbox" name="status" value="{{d.status}}" lay-skin="switch" lay-text="正常|禁用" lay-filter="statusSwitch" {{ d.status === 1 ? 'checked' : '' }}>
</script>
<script type="text/html" id="operate">
    <a class="layui-btn layui-btn-xs btn-edit" lay-event="edit">编辑</a>
    <a class="layui-btn layui-btn-xs btn-edit layui-btn-warm" lay-event="resetPwd">重置密码</a>
</script>
<script type="text/html" id="userToolbar">
    <div class="layui-btn-container">
        <button class="layui-btn layui-btn-sm layui-btn-normal" id="btn-add" lay-event="add"><i class="layui-icon">&#xe654;</i>新增</button>
        <button class="layui-btn layui-btn-sm layui-btn-danger" id="btn-delete" lay-event="del"><i class="layui-icon">&#xe640;</i>删除</button>
    </div>
</script>
<!-- 重置密码 -->
<script type="text/html" id="resetpwd-window">
    <form class="layui-form model-form">
        <input type="hidden" id="resetUserId" name="resetUserId">
        <div class="layui-form-item">
            <label class="layui-form-label layui-form-required">新密码:</label>
            <div class="layui-input-block">
                <input id="resetPassword" name="resetPassword" placeholder="请输入新密码" class="layui-input" lay-verify="required" autocomplete="off">
            </div>
        </div>
        <div class="layui-form-item text-right">
            <button class="layui-btn layui-btn-normal" id="savePwd" lay-filter="savePwd" lay-submit="">确定</button>
            <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
        </div>
    </form>
</script>
<!-- 表单弹窗 -->
<script type="text/html" id="editDialog">
    <form id="detail" lay-filter="detail" class="layui-form admin-form">
        <input name="id" type="hidden">
        <input name="status" type="hidden">
        <div class="layui-row">
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label layui-form-required">登录账户</label>
                    <div class="layui-input-block">
                        <input name="username" placeholder="请输入登录账户" class="layui-input" lay-vertype="tips" lay-verify="required" required="">
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">角色:</label>
                    <div class="layui-input-block cool-auto-complete">
                        <input name="roleId" class="layui-input" style="display: none">
                        <input id="roleName" name="roleName" class="layui-input cool-auto-complete-div" onclick="autoShow(this.id)" type="text" placeholder="请选择角色" onfocus=this.blur()>
                        <div class="cool-auto-complete-window">
                            <input class="cool-auto-complete-window-input" data-key="roleQuery" onkeyup="autoLoad(this.getAttribute('data-key'))">
                            <select class="cool-auto-complete-window-select" data-key="roleQuerySelect" onchange="confirmed(this.getAttribute('data-key'))" multiple="multiple">
                            </select>
                        </div>
                    </div>
                </div>
            </div>
            <div class="layui-col-md6">
                <div class="layui-form-item">
                    <label class="layui-form-label layui-form-required">手机号</label>
                    <div class="layui-input-block">
                        <input name="mobile" placeholder="请输入手机号" class="layui-input" lay-vertype="tips" lay-verify="required" required="">
                    </div>
                </div>
                <div class="layui-form-item">
                    <label class="layui-form-label">邮箱</label>
                    <div class="layui-input-block">
                        <input name="email" placeholder="请输入邮箱" class="layui-input">
                    </div>
                </div>
            </div>
        </div>
        <hr class="layui-bg-gray">
        <div class="layui-form-item text-right">
            <button class="layui-btn" lay-filter="editSubmit" lay-submit="">保存</button>
            <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
        </div>
    </form>
</script>
<script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
<script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
<script type="text/javascript" src="../../static/vue/element/element.js"></script>
<script type="text/javascript" src="../../static/js/common.js?v=20260309_i18n_fix1" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script>
<script type="text/javascript" src="../../static/js/tools/md5.js"></script>
<script type="text/javascript" src="../../static/js/user/user.js" charset="utf-8"></script>
<!-- 项目编辑窗口 -->
<script type="text/html" id="hostEditDialog">
    <form id="hostEditForm" lay-filter="hostEditForm" class="layui-form model-form">
        <input name="id" type="hidden"/>
        <div class="layui-form-item">
            <label class="layui-form-label layui-form-required">项目名称:</label>
            <div class="layui-input-block">
                <input name="name" placeholder="请输入类型名称" class="layui-input"
                       lay-verType="tips" lay-verify="required" required/>
            </div>
        </div>
        <div class="layui-form-item text-right">
            <button class="layui-btn" lay-filter="hostEditSubmit" lay-submit>保存</button>
            <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog">取消</button>
        </div>
    </form>
</script>
<script type="text/javascript" src="../../static/js/user/user.js?v=20260311_user_restore1" charset="utf-8"></script>
</body>
</html>