@ddj-v2/user-management 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +20 -20
- package/LICENSE +21 -21
- package/README.md +80 -77
- package/index.ts +479 -341
- package/package.json +25 -25
- package/pages/user_manage_detail.page.js +267 -267
- package/pages/user_manage_main.page.js +199 -199
- package/templates/domain_user.html +109 -0
- package/templates/user_manage_detail.html +285 -285
- package/templates/user_manage_main.html +233 -183
|
@@ -1,184 +1,234 @@
|
|
|
1
|
-
{% import "components/user.html" as user with context %}
|
|
2
|
-
{% import "components/sidemenu.html" as sidemenu with context %}
|
|
3
|
-
{% extends "manage_base.html" %}
|
|
4
|
-
|
|
5
|
-
{% block manage_content %}
|
|
6
|
-
<div class="section">
|
|
7
|
-
<div class="section__header">
|
|
8
|
-
<h1 class="section__title">{{ _('User Management') }}</h1>
|
|
9
|
-
</div>
|
|
10
|
-
|
|
11
|
-
<!-- 搜索和筛选 -->
|
|
12
|
-
<div class="section__body">
|
|
13
|
-
<form method="get" class="row">
|
|
14
|
-
<div class="medium-6 columns">
|
|
15
|
-
<label>{{ _('Search Users') }}</label>
|
|
16
|
-
<input type="text" name="search" value="{{ search }}" placeholder="{{ _('Username, Email or User ID') }}">
|
|
17
|
-
</div>
|
|
18
|
-
<div class="medium-4 columns">
|
|
19
|
-
<label>{{ _('Sort by') }}</label>
|
|
20
|
-
<select name="sort">
|
|
21
|
-
<option value="_id" {% if sort == '_id' %}selected{% endif %}>{{ _('User ID') }}</option>
|
|
22
|
-
<option value="uname" {% if sort == 'uname' %}selected{% endif %}>{{ _('Username') }}</option>
|
|
23
|
-
<option value="regat" {% if sort == 'regat' %}selected{% endif %}>{{ _('Registration Time') }}</option>
|
|
24
|
-
<option value="loginat" {% if sort == 'loginat' %}selected{% endif %}>{{ _('Last Login') }}</option>
|
|
25
|
-
<option value="priv" {% if sort == 'priv' %}selected{% endif %}>{{ _('Privilege') }}</option>
|
|
26
|
-
</select>
|
|
27
|
-
</div>
|
|
28
|
-
<div class="medium-2 columns">
|
|
29
|
-
<label> </label>
|
|
30
|
-
<button type="submit" class="expanded rounded button">{{ _('Search') }}</button>
|
|
31
|
-
</div>
|
|
32
|
-
</form>
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
<!-- 用户列表 -->
|
|
36
|
-
<div class="section__body no-padding">
|
|
37
|
-
<table class="data-table">
|
|
38
|
-
<colgroup>
|
|
39
|
-
<col class="col--uid">
|
|
40
|
-
<col class="col--user">
|
|
41
|
-
<col class="col--email">
|
|
42
|
-
<col class="col--regat">
|
|
43
|
-
<col class="col--loginat">
|
|
44
|
-
<col class="col--priv">
|
|
45
|
-
<col class="col--status">
|
|
46
|
-
<col class="col--actions">
|
|
47
|
-
</colgroup>
|
|
48
|
-
<thead>
|
|
49
|
-
<tr>
|
|
50
|
-
<th class="col--uid">{{ _('User ID') }}</th>
|
|
51
|
-
<th class="col--user">{{ _('Username') }}</th>
|
|
52
|
-
<th class="col--email">{{ _('Email') }}</th>
|
|
53
|
-
<th class="col--regat">{{ _('Registration Time') }}</th>
|
|
54
|
-
<th class="col--loginat">{{ _('Last Login') }}</th>
|
|
55
|
-
<th class="col--priv">{{ _('Privilege') }}</th>
|
|
56
|
-
<th class="col--status">{{ _('Status') }}</th>
|
|
57
|
-
<th class="col--actions">{{ _('Actions') }}</th>
|
|
58
|
-
</tr>
|
|
59
|
-
</thead>
|
|
60
|
-
<tbody>
|
|
61
|
-
{% for udoc in udocs %}
|
|
62
|
-
{% set dudoc = dudocMap[udoc._id] %}
|
|
63
|
-
<tr data-uid="{{ udoc._id }}">
|
|
64
|
-
<td class="col--uid">
|
|
65
|
-
{{ udoc._id }}
|
|
66
|
-
</td>
|
|
67
|
-
<td class="col--user">
|
|
68
|
-
{{ user.render_inline(udoc, badge=false) }}
|
|
69
|
-
{% if dudoc and dudoc.displayName %}
|
|
70
|
-
<br><small class="text-gray">{{ dudoc.displayName }}</small>
|
|
71
|
-
{% endif %}
|
|
72
|
-
</td>
|
|
73
|
-
<td class="col--email">
|
|
74
|
-
{{ udoc.mail }}
|
|
75
|
-
</td>
|
|
76
|
-
<td class="col--regat">
|
|
77
|
-
{% if udoc.regat %}
|
|
78
|
-
{{ moment(udoc.regat).format('YYYY-MM-DD HH:mm') }}
|
|
79
|
-
{% else %}
|
|
80
|
-
-
|
|
81
|
-
{% endif %}
|
|
82
|
-
</td>
|
|
83
|
-
<td class="col--loginat">
|
|
84
|
-
{% if udoc.loginat %}
|
|
85
|
-
{{ moment(udoc.loginat).format('YYYY-MM-DD HH:mm') }}
|
|
86
|
-
{% else %}
|
|
87
|
-
-
|
|
88
|
-
{% endif %}
|
|
89
|
-
</td>
|
|
90
|
-
<td class="col--priv">
|
|
91
|
-
{% if udoc.priv == -1 %}
|
|
92
|
-
<span class="badge badge--red">root</span>
|
|
93
|
-
{% elif udoc.priv == 0 %}
|
|
94
|
-
<span class="badge badge--gray">{{ _('Banned') }}</span>
|
|
95
|
-
{% elif udoc.priv == 8 %}
|
|
96
|
-
<span class="badge badge--yellow">Guest</span>
|
|
97
|
-
{% elif udoc.priv == 4 %}
|
|
98
|
-
<span class="badge badge--purple">System</span>
|
|
99
|
-
{% elif udoc.priv == 16842756 %}
|
|
100
|
-
<span class="badge badge--green">Default</span>
|
|
101
|
-
{% else %}
|
|
102
|
-
<span class="badge badge--blue">Other</span>
|
|
103
|
-
{% endif %}
|
|
104
|
-
<br><small class="text-gray">{{ udoc.priv }}</small>
|
|
105
|
-
</td>
|
|
106
|
-
<td class="col--status">
|
|
107
|
-
{% if udoc.priv == 0 %}
|
|
108
|
-
<span class="text-red">{{ _('Banned') }}</span>
|
|
109
|
-
{% else %}
|
|
110
|
-
<span class="text-green">{{ _('Active') }}</span>
|
|
111
|
-
{% endif %}
|
|
112
|
-
</td>
|
|
113
|
-
<td class="col--actions">
|
|
114
|
-
<a href="{{ url('user_manage_detail', uid=udoc._id) }}" class="button button--small">
|
|
115
|
-
{{ _('Edit') }}
|
|
116
|
-
</a>
|
|
117
|
-
</td>
|
|
118
|
-
</tr>
|
|
119
|
-
{% endfor %}
|
|
120
|
-
</tbody>
|
|
121
|
-
</table>
|
|
122
|
-
</div>
|
|
123
|
-
|
|
124
|
-
<!-- 分页 -->
|
|
125
|
-
{% if upcount > 50 %}
|
|
126
|
-
<div class="section__body">
|
|
127
|
-
<div class="row">
|
|
128
|
-
<div class="columns">
|
|
129
|
-
{% include "components/paginator.html" %}
|
|
130
|
-
</div>
|
|
131
|
-
</div>
|
|
132
|
-
</div>
|
|
133
|
-
{% endif %}
|
|
134
|
-
</div>
|
|
135
|
-
|
|
136
|
-
<style>
|
|
137
|
-
.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
.
|
|
160
|
-
.
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
.
|
|
167
|
-
.
|
|
168
|
-
.
|
|
169
|
-
|
|
170
|
-
.
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
1
|
+
{% import "components/user.html" as user with context %}
|
|
2
|
+
{% import "components/sidemenu.html" as sidemenu with context %}
|
|
3
|
+
{% extends "manage_base.html" %}
|
|
4
|
+
|
|
5
|
+
{% block manage_content %}
|
|
6
|
+
<div class="section">
|
|
7
|
+
<div class="section__header">
|
|
8
|
+
<h1 class="section__title">{{ _('User Management') }}</h1>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<!-- 搜索和筛选 -->
|
|
12
|
+
<div class="section__body">
|
|
13
|
+
<form method="get" class="row">
|
|
14
|
+
<div class="medium-6 columns">
|
|
15
|
+
<label>{{ _('Search Users') }}</label>
|
|
16
|
+
<input type="text" name="search" value="{{ search }}" placeholder="{{ _('Username, Email or User ID') }}">
|
|
17
|
+
</div>
|
|
18
|
+
<div class="medium-4 columns">
|
|
19
|
+
<label>{{ _('Sort by') }}</label>
|
|
20
|
+
<select name="sort">
|
|
21
|
+
<option value="_id" {% if sort == '_id' %}selected{% endif %}>{{ _('User ID') }}</option>
|
|
22
|
+
<option value="uname" {% if sort == 'uname' %}selected{% endif %}>{{ _('Username') }}</option>
|
|
23
|
+
<option value="regat" {% if sort == 'regat' %}selected{% endif %}>{{ _('Registration Time') }}</option>
|
|
24
|
+
<option value="loginat" {% if sort == 'loginat' %}selected{% endif %}>{{ _('Last Login') }}</option>
|
|
25
|
+
<option value="priv" {% if sort == 'priv' %}selected{% endif %}>{{ _('Privilege') }}</option>
|
|
26
|
+
</select>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="medium-2 columns">
|
|
29
|
+
<label> </label>
|
|
30
|
+
<button type="submit" class="expanded rounded button">{{ _('Search') }}</button>
|
|
31
|
+
</div>
|
|
32
|
+
</form>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<!-- 用户列表 -->
|
|
36
|
+
<div class="section__body no-padding">
|
|
37
|
+
<table class="data-table">
|
|
38
|
+
<colgroup>
|
|
39
|
+
<col class="col--uid">
|
|
40
|
+
<col class="col--user">
|
|
41
|
+
<col class="col--email">
|
|
42
|
+
<col class="col--regat">
|
|
43
|
+
<col class="col--loginat">
|
|
44
|
+
<col class="col--priv">
|
|
45
|
+
<col class="col--status">
|
|
46
|
+
<col class="col--actions">
|
|
47
|
+
</colgroup>
|
|
48
|
+
<thead>
|
|
49
|
+
<tr>
|
|
50
|
+
<th class="col--uid">{{ _('User ID') }}</th>
|
|
51
|
+
<th class="col--user">{{ _('Username') }}</th>
|
|
52
|
+
<th class="col--email">{{ _('Email') }}</th>
|
|
53
|
+
<th class="col--regat">{{ _('Registration Time') }}</th>
|
|
54
|
+
<th class="col--loginat">{{ _('Last Login') }}</th>
|
|
55
|
+
<th class="col--priv">{{ _('Privilege') }}</th>
|
|
56
|
+
<th class="col--status">{{ _('Status') }}</th>
|
|
57
|
+
<th class="col--actions">{{ _('Actions') }}</th>
|
|
58
|
+
</tr>
|
|
59
|
+
</thead>
|
|
60
|
+
<tbody>
|
|
61
|
+
{% for udoc in udocs %}
|
|
62
|
+
{% set dudoc = dudocMap[udoc._id] %}
|
|
63
|
+
<tr data-uid="{{ udoc._id }}">
|
|
64
|
+
<td class="col--uid">
|
|
65
|
+
{{ udoc._id }}
|
|
66
|
+
</td>
|
|
67
|
+
<td class="col--user">
|
|
68
|
+
{{ user.render_inline(udoc, badge=false) }}
|
|
69
|
+
{% if dudoc and dudoc.displayName %}
|
|
70
|
+
<br><small class="text-gray">{{ dudoc.displayName }}</small>
|
|
71
|
+
{% endif %}
|
|
72
|
+
</td>
|
|
73
|
+
<td class="col--email">
|
|
74
|
+
{{ udoc.mail }}
|
|
75
|
+
</td>
|
|
76
|
+
<td class="col--regat">
|
|
77
|
+
{% if udoc.regat %}
|
|
78
|
+
{{ moment(udoc.regat).format('YYYY-MM-DD HH:mm') }}
|
|
79
|
+
{% else %}
|
|
80
|
+
-
|
|
81
|
+
{% endif %}
|
|
82
|
+
</td>
|
|
83
|
+
<td class="col--loginat">
|
|
84
|
+
{% if udoc.loginat %}
|
|
85
|
+
{{ moment(udoc.loginat).format('YYYY-MM-DD HH:mm') }}
|
|
86
|
+
{% else %}
|
|
87
|
+
-
|
|
88
|
+
{% endif %}
|
|
89
|
+
</td>
|
|
90
|
+
<td class="col--priv">
|
|
91
|
+
{% if udoc.priv == -1 %}
|
|
92
|
+
<span class="badge badge--red">root</span>
|
|
93
|
+
{% elif udoc.priv == 0 %}
|
|
94
|
+
<span class="badge badge--gray">{{ _('Banned') }}</span>
|
|
95
|
+
{% elif udoc.priv == 8 %}
|
|
96
|
+
<span class="badge badge--yellow">Guest</span>
|
|
97
|
+
{% elif udoc.priv == 4 %}
|
|
98
|
+
<span class="badge badge--purple">System</span>
|
|
99
|
+
{% elif udoc.priv == 16842756 %}
|
|
100
|
+
<span class="badge badge--green">Default</span>
|
|
101
|
+
{% else %}
|
|
102
|
+
<span class="badge badge--blue">Other</span>
|
|
103
|
+
{% endif %}
|
|
104
|
+
<br><small class="text-gray">{{ udoc.priv }}</small>
|
|
105
|
+
</td>
|
|
106
|
+
<td class="col--status">
|
|
107
|
+
{% if udoc.priv == 0 %}
|
|
108
|
+
<span class="text-red">{{ _('Banned') }}</span>
|
|
109
|
+
{% else %}
|
|
110
|
+
<span class="text-green">{{ _('Active') }}</span>
|
|
111
|
+
{% endif %}
|
|
112
|
+
</td>
|
|
113
|
+
<td class="col--actions">
|
|
114
|
+
<a href="{{ url('user_manage_detail', uid=udoc._id) }}" class="button button--small">
|
|
115
|
+
{{ _('Edit') }}
|
|
116
|
+
</a>
|
|
117
|
+
</td>
|
|
118
|
+
</tr>
|
|
119
|
+
{% endfor %}
|
|
120
|
+
</tbody>
|
|
121
|
+
</table>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<!-- 分页 -->
|
|
125
|
+
{% if upcount > 50 %}
|
|
126
|
+
<div class="section__body">
|
|
127
|
+
<div class="row">
|
|
128
|
+
<div class="columns">
|
|
129
|
+
{% include "components/paginator.html" %}
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
{% endif %}
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<style>
|
|
137
|
+
.section__body.no-padding {
|
|
138
|
+
max-width: 100%;
|
|
139
|
+
overflow-x: hidden;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.data-table {
|
|
143
|
+
width: 100%;
|
|
144
|
+
table-layout: fixed;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.data-table th,
|
|
148
|
+
.data-table td {
|
|
149
|
+
word-break: break-word;
|
|
150
|
+
overflow-wrap: anywhere;
|
|
151
|
+
white-space: normal;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.data-table td {
|
|
155
|
+
max-width: 0;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.data-table td a,
|
|
159
|
+
.data-table td span,
|
|
160
|
+
.data-table td small {
|
|
161
|
+
word-break: break-word;
|
|
162
|
+
overflow-wrap: anywhere;
|
|
163
|
+
white-space: normal;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.col--uid { width: 8%; }
|
|
167
|
+
.col--user { width: 17%; }
|
|
168
|
+
.col--email { width: 19%; }
|
|
169
|
+
.col--regat { width: 13%; }
|
|
170
|
+
.col--loginat { width: 13%; }
|
|
171
|
+
.col--priv { width: 10%; }
|
|
172
|
+
.col--status { width: 8%; }
|
|
173
|
+
.col--actions { width: 12%; }
|
|
174
|
+
|
|
175
|
+
.badge {
|
|
176
|
+
display: inline-block;
|
|
177
|
+
padding: 2px 6px;
|
|
178
|
+
font-size: 11px;
|
|
179
|
+
font-weight: bold;
|
|
180
|
+
line-height: 1;
|
|
181
|
+
color: #fff;
|
|
182
|
+
text-align: center;
|
|
183
|
+
white-space: nowrap;
|
|
184
|
+
vertical-align: baseline;
|
|
185
|
+
border-radius: 3px;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.badge--red { background-color: #d9534f; }
|
|
189
|
+
.badge--blue { background-color: #5bc0de; }
|
|
190
|
+
.badge--green { background-color: #5cb85c; }
|
|
191
|
+
.badge--gray { background-color: #777; }
|
|
192
|
+
.badge--yellow { background-color: #f0ad4e; }
|
|
193
|
+
.badge--purple { background-color: #9b59b6; }
|
|
194
|
+
|
|
195
|
+
.text-red { color: #d9534f; }
|
|
196
|
+
.text-green { color: #5cb85c; }
|
|
197
|
+
.text-gray { color: #777; }
|
|
198
|
+
|
|
199
|
+
.button--small {
|
|
200
|
+
padding: 4px 8px;
|
|
201
|
+
font-size: 12px;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.col--actions .button--small {
|
|
205
|
+
display: block;
|
|
206
|
+
width: 100%;
|
|
207
|
+
max-width: 100%;
|
|
208
|
+
min-width: 0;
|
|
209
|
+
box-sizing: border-box;
|
|
210
|
+
padding: 4px 4px;
|
|
211
|
+
line-height: 1.2;
|
|
212
|
+
white-space: normal !important;
|
|
213
|
+
overflow-wrap: anywhere;
|
|
214
|
+
word-break: break-word;
|
|
215
|
+
text-align: center;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@media (max-width: 768px) {
|
|
219
|
+
.button--small {
|
|
220
|
+
padding: 3px 6px;
|
|
221
|
+
font-size: 11px;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
</style>
|
|
225
|
+
|
|
226
|
+
<script>
|
|
227
|
+
$(document).ready(function() {
|
|
228
|
+
// 排序功能:当选择框改变时自动提交表单
|
|
229
|
+
$('select[name="sort"]').on('change', function() {
|
|
230
|
+
$(this).closest('form').submit();
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
</script>
|
|
184
234
|
{% endblock %}
|