diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
diff --git a/src/collectedstatic/CACHE/css/output.20f74afba408_with_comments.css b/src/collectedstatic/CACHE/css/output.20f74afba408_with_comments.css
new file mode 100644
index 0000000..09587a8
--- /dev/null
+++ b/src/collectedstatic/CACHE/css/output.20f74afba408_with_comments.css
@@ -0,0 +1,688 @@
+/*
+ * 社交媒体图标样式
+ */
+
+/* Google 图标样式 */
+.icon-sn-google {
+ background-position: 0 -28px;
+}
+
+.icon-sn-bg-google {
+ background-color: #4285f4;
+ background-position: 0 0;
+}
+
+.fa-sn-google {
+ color: #4285f4;
+}
+
+/* GitHub 图标样式 */
+.icon-sn-github {
+ background-position: -28px -28px;
+}
+
+.icon-sn-bg-github {
+ background-color: #333;
+ background-position: -28px 0;
+}
+
+.fa-sn-github {
+ color: #333;
+}
+
+/* 微博图标样式 */
+.icon-sn-weibo {
+ background-position: -56px -28px;
+}
+
+.icon-sn-bg-weibo {
+ background-color: #e90d24;
+ background-position: -56px 0;
+}
+
+.fa-sn-weibo {
+ color: #e90d24;
+}
+
+/* QQ 图标样式 */
+.icon-sn-qq {
+ background-position: -84px -28px;
+}
+
+.icon-sn-bg-qq {
+ background-color: #0098e6;
+ background-position: -84px 0;
+}
+
+.fa-sn-qq {
+ color: #0098e6;
+}
+
+/* Twitter 图标样式 */
+.icon-sn-twitter {
+ background-position: -112px -28px;
+}
+
+.icon-sn-bg-twitter {
+ background-color: #50abf1;
+ background-position: -112px 0;
+}
+
+.fa-sn-twitter {
+ color: #50abf1;
+}
+
+/* Facebook 图标样式 */
+.icon-sn-facebook {
+ background-position: -140px -28px;
+}
+
+.icon-sn-bg-facebook {
+ background-color: #4862a3;
+ background-position: -140px 0;
+}
+
+.fa-sn-facebook {
+ color: #4862a3;
+}
+
+/* 人人网图标样式 */
+.icon-sn-renren {
+ background-position: -168px -28px;
+}
+
+.icon-sn-bg-renren {
+ background-color: #197bc8;
+ background-position: -168px 0;
+}
+
+.fa-sn-renren {
+ color: #197bc8;
+}
+
+/* 腾讯微博图标样式 */
+.icon-sn-tqq {
+ background-position: -196px -28px;
+}
+
+.icon-sn-bg-tqq {
+ background-color: #1f9ed2;
+ background-position: -196px 0;
+}
+
+.fa-sn-tqq {
+ color: #1f9ed2;
+}
+
+/* 豆瓣图标样式 */
+.icon-sn-douban {
+ background-position: -224px -28px;
+}
+
+.icon-sn-bg-douban {
+ background-color: #279738;
+ background-position: -224px 0;
+}
+
+.fa-sn-douban {
+ color: #279738;
+}
+
+/* 微信图标样式 */
+.icon-sn-weixin {
+ background-position: -252px -28px;
+}
+
+.icon-sn-bg-weixin {
+ background-color: #00b500;
+ background-position: -252px 0;
+}
+
+.fa-sn-weixin {
+ color: #00b500;
+}
+
+/* 虚线图标样式 */
+.icon-sn-dotted {
+ background-position: -280px -28px;
+}
+
+.icon-sn-bg-dotted {
+ background-color: #eee;
+ background-position: -280px 0;
+}
+
+.fa-sn-dotted {
+ color: #eee;
+}
+
+/* 站点图标样式 */
+.icon-sn-site {
+ background-position: -308px -28px;
+}
+
+.icon-sn-bg-site {
+ background-color: #00b500;
+ background-position: -308px 0;
+}
+
+.fa-sn-site {
+ color: #00b500;
+}
+
+/* LinkedIn 图标样式 */
+.icon-sn-linkedin {
+ background-position: -336px -28px;
+}
+
+.icon-sn-bg-linkedin {
+ background-color: #0077b9;
+ background-position: -336px 0;
+}
+
+.fa-sn-linkedin {
+ color: #0077b9;
+}
+
+/* 通用图标样式 */
+[class*=icon-sn-] {
+ display: inline-block;
+ background-image: url('/static/blog/img/icon-sn.svg?56272f05e520');
+ background-repeat: no-repeat;
+ width: 28px;
+ height: 28px;
+ vertical-align: middle;
+ background-size: auto 56px;
+}
+
+[class*=icon-sn-]:hover {
+ opacity: .8;
+ filter: alpha(opacity=80);
+}
+
+/*
+ * 社交媒体按钮样式
+ */
+
+/* Google 按钮样式 */
+.btn-sn-google {
+ background: #4285f4;
+}
+
+.btn-sn-google:active,
+.btn-sn-google:focus,
+.btn-sn-google:hover {
+ background: #2a75f3;
+}
+
+/* GitHub 按钮样式 */
+.btn-sn-github {
+ background: #333;
+}
+
+.btn-sn-github:active,
+.btn-sn-github:focus,
+.btn-sn-github:hover {
+ background: #262626;
+}
+
+/* 微博按钮样式 */
+.btn-sn-weibo {
+ background: #e90d24;
+}
+
+.btn-sn-weibo:active,
+.btn-sn-weibo:focus,
+.btn-sn-weibo:hover {
+ background: #d10c20;
+}
+
+/* QQ 按钮样式 */
+.btn-sn-qq {
+ background: #0098e6;
+}
+
+.btn-sn-qq:active,
+.btn-sn-qq:focus,
+.btn-sn-qq:hover {
+ background: #0087cd;
+}
+
+/* Twitter 按钮样式 */
+.btn-sn-twitter {
+ background: #50abf1;
+}
+
+.btn-sn-twitter:active,
+.btn-sn-twitter:focus,
+.btn-sn-twitter:hover {
+ background: #38a0ef;
+}
+
+/* Facebook 按钮样式 */
+.btn-sn-facebook {
+ background: #4862a3;
+}
+
+.btn-sn-facebook:active,
+.btn-sn-facebook:focus,
+.btn-sn-facebook:hover {
+ background: #405791;
+}
+
+/* 人人网按钮样式 */
+.btn-sn-renren {
+ background: #197bc8;
+}
+
+.btn-sn-renren:active,
+.btn-sn-renren:focus,
+.btn-sn-renren:hover {
+ background: #166db1;
+}
+
+/* 腾讯微博按钮样式 */
+.btn-sn-tqq {
+ background: #1f9ed2;
+}
+
+.btn-sn-tqq:active,
+.btn-sn-tqq:focus,
+.btn-sn-tqq:hover {
+ background: #1c8dbc;
+}
+
+/* 豆瓣按钮样式 */
+.btn-sn-douban {
+ background: #279738;
+}
+
+.btn-sn-douban:active,
+.btn-sn-douban:focus,
+.btn-sn-douban:hover {
+ background: #228330;
+}
+
+/* 微信按钮样式 */
+.btn-sn-weixin {
+ background: #00b500;
+}
+
+.btn-sn-weixin:active,
+.btn-sn-weixin:focus,
+.btn-sn-weixin:hover {
+ background: #009c00;
+}
+
+/* 虚线按钮样式 */
+.btn-sn-dotted {
+ background: #eee;
+}
+
+.btn-sn-dotted:active,
+.btn-sn-dotted:focus,
+.btn-sn-dotted:hover {
+ background: #e1e1e1;
+}
+
+/* 站点按钮样式 */
+.btn-sn-site {
+ background: #00b500;
+}
+
+.btn-sn-site:active,
+.btn-sn-site:focus,
+.btn-sn-site:hover {
+ background: #009c00;
+}
+
+/* LinkedIn 按钮样式 */
+.btn-sn-linkedin {
+ background: #0077b9;
+}
+
+.btn-sn-linkedin:active,
+.btn-sn-linkedin:focus,
+.btn-sn-linkedin:hover {
+ background: #0067a0;
+}
+
+/* 通用按钮样式 */
+[class*=btn-sn-],
+[class*=btn-sn-]:active,
+[class*=btn-sn-]:focus,
+[class*=btn-sn-]:hover {
+ border: none;
+ color: #fff;
+}
+
+.btn-sn-more {
+ padding: 0;
+}
+
+.btn-sn-more,
+.btn-sn-more:active,
+.btn-sn-more:hover {
+ box-shadow: none;
+}
+
+[class*=btn-sn-] [class*=icon-sn-] {
+ background-color: transparent;
+}
+
+/*
+ * 代码高亮样式
+ */
+.codehilite .hll {
+ background-color: #ffffcc;
+}
+
+.codehilite {
+ background: #ffffff;
+}
+
+.codehilite .c {
+ color: #177500;
+}
+
+.codehilite .err {
+ color: #000000;
+}
+
+.codehilite .k {
+ color: #A90D91;
+}
+
+.codehilite .l {
+ color: #1C01CE;
+}
+
+.codehilite .n {
+ color: #000000;
+}
+
+.codehilite .o {
+ color: #000000;
+}
+
+.codehilite .ch {
+ color: #177500;
+}
+
+.codehilite .cm {
+ color: #177500;
+}
+
+.codehilite .cp {
+ color: #633820;
+}
+
+.codehilite .cpf {
+ color: #177500;
+}
+
+.codehilite .c1 {
+ color: #177500;
+}
+
+.codehilite .cs {
+ color: #177500;
+}
+
+.codehilite .kc {
+ color: #A90D91;
+}
+
+.codehilite .kd {
+ color: #A90D91;
+}
+
+.codehilite .kn {
+ color: #A90D91;
+}
+
+.codehilite .kp {
+ color: #A90D91;
+}
+
+.codehilite .kr {
+ color: #A90D91;
+}
+
+.codehilite .kt {
+ color: #A90D91;
+}
+
+.codehilite .ld {
+ color: #1C01CE;
+}
+
+.codehilite .m {
+ color: #1C01CE;
+}
+
+.codehilite .s {
+ color: #C41A16;
+}
+
+.codehilite .na {
+ color: #836C28;
+}
+
+.codehilite .nb {
+ color: #A90D91;
+}
+
+.codehilite .nc {
+ color: #3F6E75;
+}
+
+.codehilite .no {
+ color: #000000;
+}
+
+.codehilite .nd {
+ color: #000000;
+}
+
+.codehilite .ni {
+ color: #000000;
+}
+
+.codehilite .ne {
+ color: #000000;
+}
+
+.codehilite .nf {
+ color: #000000;
+}
+
+.codehilite .nl {
+ color: #000000;
+}
+
+.codehilite .nn {
+ color: #000000;
+}
+
+.codehilite .nx {
+ color: #000000;
+}
+
+.codehilite .py {
+ color: #000000;
+}
+
+.codehilite .nt {
+ color: #000000;
+}
+
+.codehilite .nv {
+ color: #000000;
+}
+
+.codehilite .ow {
+ color: #000000;
+}
+
+.codehilite .mb {
+ color: #1C01CE;
+}
+
+.codehilite .mf {
+ color: #1C01CE;
+}
+
+.codehilite .mh {
+ color: #1C01CE;
+}
+
+.codehilite .mi {
+ color: #1C01CE;
+}
+
+.codehilite .mo {
+ color: #1C01CE;
+}
+
+.codehilite .sb {
+ color: #C41A16;
+}
+
+.codehilite .sc {
+ color: #2300CE;
+}
+
+.codehilite .sd {
+ color: #C41A16;
+}
+
+.codehilite .s2 {
+ color: #C41A16;
+}
+
+.codehilite .se {
+ color: #C41A16;
+}
+
+.codehilite .sh {
+ color: #C41A16;
+}
+
+.codehilite .si {
+ color: #C41A16;
+}
+
+.codehilite .sx {
+ color: #C41A16;
+}
+
+.codehilite .sr {
+ color: #C41A16;
+}
+
+.codehilite .s1 {
+ color: #C41A16;
+}
+
+.codehilite .ss {
+ color: #C41A16;
+}
+
+.codehilite .bp {
+ color: #5B269A;
+}
+
+.codehilite .vc {
+ color: #000000;
+}
+
+.codehilite .vg {
+ color: #000000;
+}
+
+.codehilite .vi {
+ color: #000000;
+}
+
+.codehilite .il {
+ color: #1C01CE;
+}
+
+/*
+ * 进度条样式 (NProgress)
+ */
+#nprogress {
+ pointer-events: none;
+}
+
+#nprogress .bar {
+ background: red;
+ position: fixed;
+ z-index: 1031;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 2px;
+}
+
+#nprogress .peg {
+ display: block;
+ position: absolute;
+ right: 0px;
+ width: 100px;
+ height: 100%;
+ box-shadow: 0 0 10px #29d, 0 0 5px #29d;
+ opacity: 1.0;
+ -webkit-transform: rotate(3deg) translate(0px, -4px);
+ -ms-transform: rotate(3deg) translate(0px, -4px);
+ transform: rotate(3deg) translate(0px, -4px);
+}
+
+#nprogress .spinner {
+ display: block;
+ position: fixed;
+ z-index: 1031;
+ top: 15px;
+ right: 15px;
+}
+
+#nprogress .spinner-icon {
+ width: 18px;
+ height: 18px;
+ box-sizing: border-box;
+ border: solid 2px transparent;
+ border-top-color: red;
+ border-left-color: red;
+ border-radius: 50%;
+ -webkit-animation: nprogress-spinner 400ms linear infinite;
+ animation: nprogress-spinner 400ms linear infinite;
+}
+
+.nprogress-custom-parent {
+ overflow: hidden;
+ position: relative;
+}
+
+.nprogress-custom-parent #nprogress .spinner,
+.nprogress-custom-parent #nprogress .bar {
+ position: absolute;
+}
+
+@-webkit-keyframes nprogress-spinner {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ }
+}
+
+@keyframes nprogress-spinner {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
\ No newline at end of file
diff --git a/src/collectedstatic/CACHE/css/output.5ee9ff3cb1a7_with_comments.css b/src/collectedstatic/CACHE/css/output.5ee9ff3cb1a7_with_comments.css
new file mode 100644
index 0000000..c3a74e4
--- /dev/null
+++ b/src/collectedstatic/CACHE/css/output.5ee9ff3cb1a7_with_comments.css
@@ -0,0 +1,1846 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
+
+/*
+ * HTML5显示定义
+ * 正确显示HTML5新增元素
+ */
+html {
+ font-family: sans-serif;
+ -webkit-text-size-adjust: 100%;
+ -ms-text-size-adjust: 100%;
+}
+
+body {
+ margin: 0;
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+
+audio,
+canvas,
+progress,
+video {
+ display: inline-block;
+ vertical-align: baseline;
+}
+
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+
+[hidden],
+template {
+ display: none;
+}
+
+/*
+ * 链接样式
+ */
+a {
+ background-color: transparent;
+}
+
+a:active,
+a:hover {
+ outline: 0;
+}
+
+/*
+ * 文本样式
+ */
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+
+b,
+strong {
+ font-weight: bold;
+}
+
+dfn {
+ font-style: italic;
+}
+
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+
+mark {
+ background: #ff0;
+ color: #000;
+}
+
+small {
+ font-size: 80%;
+}
+
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+
+sup {
+ top: -0.5em;
+}
+
+sub {
+ bottom: -0.25em;
+}
+
+/*
+ * 嵌入内容样式
+ */
+img {
+ border: 0;
+}
+
+svg:not(:root) {
+ overflow: hidden;
+}
+
+/*
+ * 图片和表格样式
+ */
+figure {
+ margin: 1em 40px;
+}
+
+hr {
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 0;
+}
+
+pre {
+ overflow: auto;
+}
+
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+
+/*
+ * 表单样式
+ */
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit;
+ font: inherit;
+ margin: 0;
+}
+
+button {
+ overflow: visible;
+}
+
+button,
+select {
+ text-transform: none;
+}
+
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button;
+ cursor: pointer;
+}
+
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+
+input {
+ line-height: normal;
+}
+
+input[type="checkbox"],
+input[type="radio"] {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ padding: 0;
+}
+
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+
+input[type="search"] {
+ -webkit-appearance: textfield;
+ -webkit-box-sizing: content-box;
+ -moz-box-sizing: content-box;
+ box-sizing: content-box;
+}
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+
+legend {
+ border: 0;
+ padding: 0;
+}
+
+textarea {
+ overflow: auto;
+}
+
+optgroup {
+ font-weight: bold;
+}
+
+/*
+ * 表格样式
+ */
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+td,
+th {
+ padding: 0;
+}
+
+/*
+ * 打印样式
+ */
+@media print {
+ *,
+ *:before,
+ *:after {
+ background: transparent !important;
+ color: #000 !important;
+ -webkit-box-shadow: none !important;
+ box-shadow: none !important;
+ text-shadow: none !important;
+ }
+
+ a,
+ a:visited {
+ text-decoration: underline;
+ }
+
+ a[href]:after {
+ content: " (" attr(href) ")";
+ }
+
+ abbr[title]:after {
+ content: " (" attr(title) ")";
+ }
+
+ a[href^="#"]:after,
+ a[href^="javascript:"]:after {
+ content: "";
+ }
+
+ pre,
+ blockquote {
+ border: 1px solid #999;
+ page-break-inside: avoid;
+ }
+
+ thead {
+ display: table-header-group;
+ }
+
+ tr,
+ img {
+ page-break-inside: avoid;
+ }
+
+ img {
+ max-width: 100% !important;
+ }
+
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3;
+ }
+
+ h2,
+ h3 {
+ page-break-after: avoid;
+ }
+
+ .navbar {
+ display: none;
+ }
+
+ .btn > .caret,
+ .dropup > .btn > .caret {
+ border-top-color: #000 !important;
+ }
+
+ .label {
+ border: 1px solid #000;
+ }
+
+ .table {
+ border-collapse: collapse !important;
+ }
+
+ .table td,
+ .table th {
+ background-color: #fff !important;
+ }
+
+ .table-bordered th,
+ .table-bordered td {
+ border: 1px solid #ddd !important;
+ }
+}
+
+/*
+ * Glyphicons 字体图标
+ */
+@font-face {
+ font-family: 'Glyphicons Halflings';
+ src: url('../fonts/glyphicons-halflings-regular.eot');
+ src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),
+ url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'),
+ url('../fonts/glyphicons-halflings-regular.woff') format('woff'),
+ url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'),
+ url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
+}
+
+.glyphicon {
+ position: relative;
+ top: 1px;
+ display: inline-block;
+ font-family: 'Glyphicons Halflings';
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+/*
+ * Glyphicons 图标定义
+ */
+.glyphicon-asterisk:before {
+ content: "\002a";
+}
+
+.glyphicon-plus:before {
+ content: "\002b";
+}
+
+.glyphicon-eur:before,
+.glyphicon-euro:before {
+ content: "\20ac";
+}
+
+.glyphicon-minus:before {
+ content: "\2212";
+}
+
+.glyphicon-cloud:before {
+ content: "\2601";
+}
+
+.glyphicon-envelope:before {
+ content: "\2709";
+}
+
+.glyphicon-pencil:before {
+ content: "\270f";
+}
+
+.glyphicon-glass:before {
+ content: "\e001";
+}
+
+.glyphicon-music:before {
+ content: "\e002";
+}
+
+.glyphicon-search:before {
+ content: "\e003";
+}
+
+.glyphicon-heart:before {
+ content: "\e005";
+}
+
+.glyphicon-star:before {
+ content: "\e006";
+}
+
+.glyphicon-star-empty:before {
+ content: "\e007";
+}
+
+.glyphicon-user:before {
+ content: "\e008";
+}
+
+.glyphicon-film:before {
+ content: "\e009";
+}
+
+.glyphicon-th-large:before {
+ content: "\e010";
+}
+
+.glyphicon-th:before {
+ content: "\e011";
+}
+
+.glyphicon-th-list:before {
+ content: "\e012";
+}
+
+.glyphicon-ok:before {
+ content: "\e013";
+}
+
+.glyphicon-remove:before {
+ content: "\e014";
+}
+
+.glyphicon-zoom-in:before {
+ content: "\e015";
+}
+
+.glyphicon-zoom-out:before {
+ content: "\e016";
+}
+
+.glyphicon-off:before {
+ content: "\e017";
+}
+
+.glyphicon-signal:before {
+ content: "\e018";
+}
+
+.glyphicon-cog:before {
+ content: "\e019";
+}
+
+.glyphicon-trash:before {
+ content: "\e020";
+}
+
+.glyphicon-home:before {
+ content: "\e021";
+}
+
+.glyphicon-file:before {
+ content: "\e022";
+}
+
+.glyphicon-time:before {
+ content: "\e023";
+}
+
+.glyphicon-road:before {
+ content: "\e024";
+}
+
+.glyphicon-download-alt:before {
+ content: "\e025";
+}
+
+.glyphicon-download:before {
+ content: "\e026";
+}
+
+.glyphicon-upload:before {
+ content: "\e027";
+}
+
+.glyphicon-inbox:before {
+ content: "\e028";
+}
+
+.glyphicon-play-circle:before {
+ content: "\e029";
+}
+
+.glyphicon-repeat:before {
+ content: "\e030";
+}
+
+.glyphicon-refresh:before {
+ content: "\e031";
+}
+
+.glyphicon-list-alt:before {
+ content: "\e032";
+}
+
+.glyphicon-lock:before {
+ content: "\e033";
+}
+
+.glyphicon-flag:before {
+ content: "\e034";
+}
+
+.glyphicon-headphones:before {
+ content: "\e035";
+}
+
+.glyphicon-volume-off:before {
+ content: "\e036";
+}
+
+.glyphicon-volume-down:before {
+ content: "\e037";
+}
+
+.glyphicon-volume-up:before {
+ content: "\e038";
+}
+
+.glyphicon-qrcode:before {
+ content: "\e039";
+}
+
+.glyphicon-barcode:before {
+ content: "\e040";
+}
+
+.glyphicon-tag:before {
+ content: "\e041";
+}
+
+.glyphicon-tags:before {
+ content: "\e042";
+}
+
+.glyphicon-book:before {
+ content: "\e043";
+}
+
+.glyphicon-bookmark:before {
+ content: "\e044";
+}
+
+.glyphicon-print:before {
+ content: "\e045";
+}
+
+.glyphicon-camera:before {
+ content: "\e046";
+}
+
+.glyphicon-font:before {
+ content: "\e047";
+}
+
+.glyphicon-bold:before {
+ content: "\e048";
+}
+
+.glyphicon-italic:before {
+ content: "\e049";
+}
+
+.glyphicon-text-height:before {
+ content: "\e050";
+}
+
+.glyphicon-text-width:before {
+ content: "\e051";
+}
+
+.glyphicon-align-left:before {
+ content: "\e052";
+}
+
+.glyphicon-align-center:before {
+ content: "\e053";
+}
+
+.glyphicon-align-right:before {
+ content: "\e054";
+}
+
+.glyphicon-align-justify:before {
+ content: "\e055";
+}
+
+.glyphicon-list:before {
+ content: "\e056";
+}
+
+.glyphicon-indent-left:before {
+ content: "\e057";
+}
+
+.glyphicon-indent-right:before {
+ content: "\e058";
+}
+
+.glyphicon-facetime-video:before {
+ content: "\e059";
+}
+
+.glyphicon-picture:before {
+ content: "\e060";
+}
+
+.glyphicon-map-marker:before {
+ content: "\e062";
+}
+
+.glyphicon-adjust:before {
+ content: "\e063";
+}
+
+.glyphicon-tint:before {
+ content: "\e064";
+}
+
+.glyphicon-edit:before {
+ content: "\e065";
+}
+
+.glyphicon-share:before {
+ content: "\e066";
+}
+
+.glyphicon-check:before {
+ content: "\e067";
+}
+
+.glyphicon-move:before {
+ content: "\e068";
+}
+
+.glyphicon-step-backward:before {
+ content: "\e069";
+}
+
+.glyphicon-fast-backward:before {
+ content: "\e070";
+}
+
+.glyphicon-backward:before {
+ content: "\e071";
+}
+
+.glyphicon-play:before {
+ content: "\e072";
+}
+
+.glyphicon-pause:before {
+ content: "\e073";
+}
+
+.glyphicon-stop:before {
+ content: "\e074";
+}
+
+.glyphicon-forward:before {
+ content: "\e075";
+}
+
+.glyphicon-fast-forward:before {
+ content: "\e076";
+}
+
+.glyphicon-step-forward:before {
+ content: "\e077";
+}
+
+.glyphicon-eject:before {
+ content: "\e078";
+}
+
+.glyphicon-chevron-left:before {
+ content: "\e079";
+}
+
+.glyphicon-chevron-right:before {
+ content: "\e080";
+}
+
+.glyphicon-plus-sign:before {
+ content: "\e081";
+}
+
+.glyphicon-minus-sign:before {
+ content: "\e082";
+}
+
+.glyphicon-remove-sign:before {
+ content: "\e083";
+}
+
+.glyphicon-ok-sign:before {
+ content: "\e084";
+}
+
+.glyphicon-question-sign:before {
+ content: "\e085";
+}
+
+.glyphicon-info-sign:before {
+ content: "\e086";
+}
+
+.glyphicon-screenshot:before {
+ content: "\e087";
+}
+
+.glyphicon-remove-circle:before {
+ content: "\e088";
+}
+
+.glyphicon-ok-circle:before {
+ content: "\e089";
+}
+
+.glyphicon-ban-circle:before {
+ content: "\e090";
+}
+
+.glyphicon-arrow-left:before {
+ content: "\e091";
+}
+
+.glyphicon-arrow-right:before {
+ content: "\e092";
+}
+
+.glyphicon-arrow-up:before {
+ content: "\e093";
+}
+
+.glyphicon-arrow-down:before {
+ content: "\e094";
+}
+
+.glyphicon-share-alt:before {
+ content: "\e095";
+}
+
+.glyphicon-resize-full:before {
+ content: "\e096";
+}
+
+.glyphicon-resize-small:before {
+ content: "\e097";
+}
+
+.glyphicon-exclamation-sign:before {
+ content: "\e101";
+}
+
+.glyphicon-gift:before {
+ content: "\e102";
+}
+
+.glyphicon-leaf:before {
+ content: "\e103";
+}
+
+.glyphicon-fire:before {
+ content: "\e104";
+}
+
+.glyphicon-eye-open:before {
+ content: "\e105";
+}
+
+.glyphicon-eye-close:before {
+ content: "\e106";
+}
+
+.glyphicon-warning-sign:before {
+ content: "\e107";
+}
+
+.glyphicon-plane:before {
+ content: "\e108";
+}
+
+.glyphicon-calendar:before {
+ content: "\e109";
+}
+
+.glyphicon-random:before {
+ content: "\e110";
+}
+
+.glyphicon-comment:before {
+ content: "\e111";
+}
+
+.glyphicon-magnet:before {
+ content: "\e112";
+}
+
+.glyphicon-chevron-up:before {
+ content: "\e113";
+}
+
+.glyphicon-chevron-down:before {
+ content: "\e114";
+}
+
+.glyphicon-retweet:before {
+ content: "\e115";
+}
+
+.glyphicon-shopping-cart:before {
+ content: "\e116";
+}
+
+.glyphicon-folder-close:before {
+ content: "\e117";
+}
+
+.glyphicon-folder-open:before {
+ content: "\e118";
+}
+
+.glyphicon-resize-vertical:before {
+ content: "\e119";
+}
+
+.glyphicon-resize-horizontal:before {
+ content: "\e120";
+}
+
+.glyphicon-hdd:before {
+ content: "\e121";
+}
+
+.glyphicon-bullhorn:before {
+ content: "\e122";
+}
+
+.glyphicon-bell:before {
+ content: "\e123";
+}
+
+.glyphicon-certificate:before {
+ content: "\e124";
+}
+
+.glyphicon-thumbs-up:before {
+ content: "\e125";
+}
+
+.glyphicon-thumbs-down:before {
+ content: "\e126";
+}
+
+.glyphicon-hand-right:before {
+ content: "\e127";
+}
+
+.glyphicon-hand-left:before {
+ content: "\e128";
+}
+
+.glyphicon-hand-up:before {
+ content: "\e129";
+}
+
+.glyphicon-hand-down:before {
+ content: "\e130";
+}
+
+.glyphicon-circle-arrow-right:before {
+ content: "\e131";
+}
+
+.glyphicon-circle-arrow-left:before {
+ content: "\e132";
+}
+
+.glyphicon-circle-arrow-up:before {
+ content: "\e133";
+}
+
+.glyphicon-circle-arrow-down:before {
+ content: "\e134";
+}
+
+.glyphicon-globe:before {
+ content: "\e135";
+}
+
+.glyphicon-wrench:before {
+ content: "\e136";
+}
+
+.glyphicon-tasks:before {
+ content: "\e137";
+}
+
+.glyphicon-filter:before {
+ content: "\e138";
+}
+
+.glyphicon-briefcase:before {
+ content: "\e139";
+}
+
+.glyphicon-fullscreen:before {
+ content: "\e140";
+}
+
+.glyphicon-dashboard:before {
+ content: "\e141";
+}
+
+.glyphicon-paperclip:before {
+ content: "\e142";
+}
+
+.glyphicon-heart-empty:before {
+ content: "\e143";
+}
+
+.glyphicon-link:before {
+ content: "\e144";
+}
+
+.glyphicon-phone:before {
+ content: "\e145";
+}
+
+.glyphicon-pushpin:before {
+ content: "\e146";
+}
+
+.glyphicon-usd:before {
+ content: "\e148";
+}
+
+.glyphicon-gbp:before {
+ content: "\e149";
+}
+
+.glyphicon-sort:before {
+ content: "\e150";
+}
+
+.glyphicon-sort-by-alphabet:before {
+ content: "\e151";
+}
+
+.glyphicon-sort-by-alphabet-alt:before {
+ content: "\e152";
+}
+
+.glyphicon-sort-by-order:before {
+ content: "\e153";
+}
+
+.glyphicon-sort-by-order-alt:before {
+ content: "\e154";
+}
+
+.glyphicon-sort-by-attributes:before {
+ content: "\e155";
+}
+
+.glyphicon-sort-by-attributes-alt:before {
+ content: "\e156";
+}
+
+.glyphicon-unchecked:before {
+ content: "\e157";
+}
+
+.glyphicon-expand:before {
+ content: "\e158";
+}
+
+.glyphicon-collapse-down:before {
+ content: "\e159";
+}
+
+.glyphicon-collapse-up:before {
+ content: "\e160";
+}
+
+.glyphicon-log-in:before {
+ content: "\e161";
+}
+
+.glyphicon-flash:before {
+ content: "\e162";
+}
+
+.glyphicon-log-out:before {
+ content: "\e163";
+}
+
+.glyphicon-new-window:before {
+ content: "\e164";
+}
+
+.glyphicon-record:before {
+ content: "\e165";
+}
+
+.glyphicon-save:before {
+ content: "\e166";
+}
+
+.glyphicon-open:before {
+ content: "\e167";
+}
+
+.glyphicon-saved:before {
+ content: "\e168";
+}
+
+.glyphicon-import:before {
+ content: "\e169";
+}
+
+.glyphicon-export:before {
+ content: "\e170";
+}
+
+.glyphicon-send:before {
+ content: "\e171";
+}
+
+.glyphicon-floppy-disk:before {
+ content: "\e172";
+}
+
+.glyphicon-floppy-saved:before {
+ content: "\e173";
+}
+
+.glyphicon-floppy-remove:before {
+ content: "\e174";
+}
+
+.glyphicon-floppy-save:before {
+ content: "\e175";
+}
+
+.glyphicon-floppy-open:before {
+ content: "\e176";
+}
+
+.glyphicon-credit-card:before {
+ content: "\e177";
+}
+
+.glyphicon-transfer:before {
+ content: "\e178";
+}
+
+.glyphicon-cutlery:before {
+ content: "\e179";
+}
+
+.glyphicon-header:before {
+ content: "\e180";
+}
+
+.glyphicon-compressed:before {
+ content: "\e181";
+}
+
+.glyphicon-earphone:before {
+ content: "\e182";
+}
+
+.glyphicon-phone-alt:before {
+ content: "\e183";
+}
+
+.glyphicon-tower:before {
+ content: "\e184";
+}
+
+.glyphicon-stats:before {
+ content: "\e185";
+}
+
+.glyphicon-sd-video:before {
+ content: "\e186";
+}
+
+.glyphicon-hd-video:before {
+ content: "\e187";
+}
+
+.glyphicon-subtitles:before {
+ content: "\e188";
+}
+
+.glyphicon-sound-stereo:before {
+ content: "\e189";
+}
+
+.glyphicon-sound-dolby:before {
+ content: "\e190";
+}
+
+.glyphicon-sound-5-1:before {
+ content: "\e191";
+}
+
+.glyphicon-sound-6-1:before {
+ content: "\e192";
+}
+
+.glyphicon-sound-7-1:before {
+ content: "\e193";
+}
+
+.glyphicon-copyright-mark:before {
+ content: "\e194";
+}
+
+.glyphicon-registration-mark:before {
+ content: "\e195";
+}
+
+.glyphicon-cloud-download:before {
+ content: "\e197";
+}
+
+.glyphicon-cloud-upload:before {
+ content: "\e198";
+}
+
+.glyphicon-tree-conifer:before {
+ content: "\e199";
+}
+
+.glyphicon-tree-deciduous:before {
+ content: "\e200";
+}
+
+.glyphicon-cd:before {
+ content: "\e201";
+}
+
+.glyphicon-save-file:before {
+ content: "\e202";
+}
+
+.glyphicon-open-file:before {
+ content: "\e203";
+}
+
+.glyphicon-level-up:before {
+ content: "\e204";
+}
+
+.glyphicon-copy:before {
+ content: "\e205";
+}
+
+.glyphicon-paste:before {
+ content: "\e206";
+}
+
+.glyphicon-alert:before {
+ content: "\e209";
+}
+
+.glyphicon-equalizer:before {
+ content: "\e210";
+}
+
+.glyphicon-king:before {
+ content: "\e211";
+}
+
+.glyphicon-queen:before {
+ content: "\e212";
+}
+
+.glyphicon-pawn:before {
+ content: "\e213";
+}
+
+.glyphicon-bishop:before {
+ content: "\e214";
+}
+
+.glyphicon-knight:before {
+ content: "\e215";
+}
+
+.glyphicon-baby-formula:before {
+ content: "\e216";
+}
+
+.glyphicon-tent:before {
+ content: "\26fa";
+}
+
+.glyphicon-blackboard:before {
+ content: "\e218";
+}
+
+.glyphicon-bed:before {
+ content: "\e219";
+}
+
+.glyphicon-apple:before {
+ content: "\f8ff";
+}
+
+.glyphicon-erase:before {
+ content: "\e221";
+}
+
+.glyphicon-hourglass:before {
+ content: "\231b";
+}
+
+.glyphicon-lamp:before {
+ content: "\e223";
+}
+
+.glyphicon-duplicate:before {
+ content: "\e224";
+}
+
+.glyphicon-piggy-bank:before {
+ content: "\e225";
+}
+
+.glyphicon-scissors:before {
+ content: "\e226";
+}
+
+.glyphicon-bitcoin:before {
+ content: "\e227";
+}
+
+.glyphicon-btc:before {
+ content: "\e227";
+}
+
+.glyphicon-xbt:before {
+ content: "\e227";
+}
+
+.glyphicon-yen:before {
+ content: "\00a5";
+}
+
+.glyphicon-jpy:before {
+ content: "\00a5";
+}
+
+.glyphicon-ruble:before {
+ content: "\20bd";
+}
+
+.glyphicon-rub:before {
+ content: "\20bd";
+}
+
+.glyphicon-scale:before {
+ content: "\e230";
+}
+
+.glyphicon-ice-lolly:before {
+ content: "\e231";
+}
+
+.glyphicon-ice-lolly-tasted:before {
+ content: "\e232";
+}
+
+.glyphicon-education:before {
+ content: "\e233";
+}
+
+.glyphicon-option-horizontal:before {
+ content: "\e234";
+}
+
+.glyphicon-option-vertical:before {
+ content: "\e235";
+}
+
+.glyphicon-menu-hamburger:before {
+ content: "\e236";
+}
+
+.glyphicon-modal-window:before {
+ content: "\e237";
+}
+
+.glyphicon-oil:before {
+ content: "\e238";
+}
+
+.glyphicon-grain:before {
+ content: "\e239";
+}
+
+.glyphicon-sunglasses:before {
+ content: "\e240";
+}
+
+.glyphicon-text-size:before {
+ content: "\e241";
+}
+
+.glyphicon-text-color:before {
+ content: "\e242";
+}
+
+.glyphicon-text-background:before {
+ content: "\e243";
+}
+
+.glyphicon-object-align-top:before {
+ content: "\e244";
+}
+
+.glyphicon-object-align-bottom:before {
+ content: "\e245";
+}
+
+.glyphicon-object-align-horizontal:before {
+ content: "\e246";
+}
+
+.glyphicon-object-align-left:before {
+ content: "\e247";
+}
+
+.glyphicon-object-align-vertical:before {
+ content: "\e248";
+}
+
+.glyphicon-object-align-right:before {
+ content: "\e249";
+}
+
+.glyphicon-triangle-right:before {
+ content: "\e250";
+}
+
+.glyphicon-triangle-left:before {
+ content: "\e251";
+}
+
+.glyphicon-triangle-bottom:before {
+ content: "\e252";
+}
+
+.glyphicon-triangle-top:before {
+ content: "\e253";
+}
+
+.glyphicon-console:before {
+ content: "\e254";
+}
+
+.glyphicon-superscript:before {
+ content: "\e255";
+}
+
+.glyphicon-subscript:before {
+ content: "\e256";
+}
+
+.glyphicon-menu-left:before {
+ content: "\e257";
+}
+
+.glyphicon-menu-right:before {
+ content: "\e258";
+}
+
+.glyphicon-menu-down:before {
+ content: "\e259";
+}
+
+.glyphicon-menu-up:before {
+ content: "\e260";
+}
+
+/*
+ * 布局样式
+ */
+* {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+*:before,
+*:after {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+html {
+ font-size: 10px;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+body {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #333;
+ background-color: #fff;
+}
+
+/*
+ * 链接样式
+ */
+a {
+ color: #337ab7;
+ text-decoration: none;
+}
+
+a:hover,
+a:focus {
+ color: #23527c;
+ text-decoration: underline;
+}
+
+a:focus {
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+/*
+ * 图片样式
+ */
+img {
+ vertical-align: middle;
+}
+
+.img-responsive {
+ display: block;
+ max-width: 100%;
+ height: auto;
+}
+
+.img-rounded {
+ border-radius: 6px;
+}
+
+.img-thumbnail {
+ padding: 4px;
+ line-height: 1.42857143;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ -webkit-transition: all 0.2s ease-in-out;
+ -o-transition: all 0.2s ease-in-out;
+ transition: all 0.2s ease-in-out;
+ display: inline-block;
+ max-width: 100%;
+ height: auto;
+}
+
+.img-circle {
+ border-radius: 50%;
+}
+
+/*
+ * 表格样式
+ */
+table {
+ background-color: transparent;
+}
+
+caption {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ color: #777;
+ text-align: left;
+}
+
+th {
+ text-align: left;
+}
+
+.table {
+ width: 100%;
+ max-width: 100%;
+ margin-bottom: 20px;
+}
+
+.table > thead > tr > th,
+.table > tbody > tr > th,
+.table > tfoot > tr > th,
+.table > thead > tr > td,
+.table > tbody > tr > td,
+.table > tfoot > tr > td {
+ padding: 8px;
+ line-height: 1.42857143;
+ vertical-align: top;
+ border-top: 1px solid #ddd;
+}
+
+.table > thead > tr > th {
+ vertical-align: bottom;
+ border-bottom: 2px solid #ddd;
+}
+
+.table > caption + thead > tr:first-child > th,
+.table > colgroup + thead > tr:first-child > th,
+.table > thead:first-child > tr:first-child > th,
+.table > caption + thead > tr:first-child > td,
+.table > colgroup + thead > tr:first-child > td,
+.table > thead:first-child > tr:first-child > td {
+ border-top: 0;
+}
+
+.table > tbody + tbody {
+ border-top: 2px solid #ddd;
+}
+
+.table .table {
+ background-color: #fff;
+}
+
+/*
+ * 表单样式
+ */
+.form-control {
+ display: block;
+ width: 100%;
+ height: 34px;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ color: #555;
+ background-color: #fff;
+ background-image: none;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -webkit-transition: border-color ease-in-out 0.15s, -webkit-box-shadow ease-in-out 0.15s;
+ -o-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+ transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+}
+
+.form-control:focus {
+ border-color: #66afe9;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+
+.form-control::-moz-placeholder {
+ color: #999;
+ opacity: 1;
+}
+
+.form-control:-ms-input-placeholder {
+ color: #999;
+}
+
+.form-control::-webkit-input-placeholder {
+ color: #999;
+}
+
+/*
+ * 按钮样式
+ */
+.btn {
+ display: inline-block;
+ margin-bottom: 0;
+ font-weight: normal;
+ text-align: center;
+ vertical-align: middle;
+ -ms-touch-action: manipulation;
+ touch-action: manipulation;
+ cursor: pointer;
+ background-image: none;
+ border: 1px solid transparent;
+ white-space: nowrap;
+ padding: 6px 12px;
+ font-size: 14px;
+ line-height: 1.42857143;
+ border-radius: 4px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.btn:focus,
+.btn:active:focus,
+.btn.active:focus,
+.btn.focus,
+.btn:active.focus,
+.btn.active.focus {
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+
+.btn:hover,
+.btn:focus,
+.btn.focus {
+ color: #333;
+ text-decoration: none;
+}
+
+.btn:active,
+.btn.active {
+ background-image: none;
+ outline: 0;
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+ cursor: not-allowed;
+ filter: alpha(opacity=65);
+ opacity: 0.65;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+
+/*
+ * 导航样式
+ */
+.nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+}
+
+.nav > li {
+ position: relative;
+ display: block;
+}
+
+.nav > li > a {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+}
+
+.nav > li > a:hover,
+.nav > li > a:focus {
+ text-decoration: none;
+ background-color: #eee;
+}
+
+.nav .open > a,
+.nav .open > a:hover,
+.nav .open > a:focus {
+ background-color: #eee;
+ border-color: #337ab7;
+}
+
+.nav-tabs {
+ border-bottom: 1px solid #ddd;
+}
+
+.nav-tabs > li {
+ float: left;
+ margin-bottom: -1px;
+}
+
+.nav-tabs > li > a {
+ margin-right: 2px;
+ line-height: 1.42857143;
+ border: 1px solid transparent;
+ border-radius: 4px 4px 0 0;
+}
+
+.nav-tabs > li > a:hover {
+ border-color: #eee #eee #ddd;
+}
+
+.nav-tabs > li.active > a,
+.nav-tabs > li.active > a:hover,
+.nav-tabs > li.active > a:focus {
+ color: #555;
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-bottom-color: transparent;
+ cursor: default;
+}
+
+/*
+ * 导航栏样式
+ */
+.navbar {
+ position: relative;
+ min-height: 50px;
+ margin-bottom: 20px;
+ border: 1px solid transparent;
+}
+
+@media (min-width: 768px) {
+ .navbar {
+ border-radius: 4px;
+ }
+}
+
+.navbar-brand {
+ float: left;
+ padding: 15px 15px;
+ font-size: 18px;
+ line-height: 20px;
+ height: 50px;
+}
+
+.navbar-brand:hover,
+.navbar-brand:focus {
+ text-decoration: none;
+}
+
+.navbar-nav {
+ margin: 7.5px -15px;
+}
+
+.navbar-nav > li > a {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ line-height: 20px;
+}
+
+@media (min-width: 768px) {
+ .navbar-nav {
+ float: left;
+ margin: 0;
+ }
+
+ .navbar-nav > li {
+ float: left;
+ }
+
+ .navbar-nav > li > a {
+ padding-top: 15px;
+ padding-bottom: 15px;
+ }
+}
+
+/*
+ * 面板样式
+ */
+.panel {
+ margin-bottom: 20px;
+ background-color: #fff;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+
+.panel-body {
+ padding: 15px;
+}
+
+.panel-heading {
+ padding: 10px 15px;
+ border-bottom: 1px solid transparent;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+
+.panel-title {
+ margin-top: 0;
+ margin-bottom: 0;
+ font-size: 16px;
+ color: inherit;
+}
+
+.panel-footer {
+ padding: 10px 15px;
+ background-color: #f5f5f5;
+ border-top: 1px solid #ddd;
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+
+/*
+ * 响应式工具类
+ */
+@media (max-width: 767px) {
+ .hidden-xs {
+ display: none !important;
+ }
+}
+
+@media (min-width: 768px) and (max-width: 991px) {
+ .hidden-sm {
+ display: none !important;
+ }
+}
+
+@media (min-width: 992px) and (max-width: 1199px) {
+ .hidden-md {
+ display: none !important;
+ }
+}
+
+@media (min-width: 1200px) {
+ .hidden-lg {
+ display: none !important;
+ }
+}
\ No newline at end of file
diff --git a/src/collectedstatic/account/css/account.css b/src/collectedstatic/account/css/account.css
index 7d4cec7..1ecf43b 100644
--- a/src/collectedstatic/account/css/account.css
+++ b/src/collectedstatic/account/css/account.css
@@ -1,9 +1,25 @@
+/* 按钮样式 */
+/* Button styles */
.button {
+ /* 移除边框 */
+ /* Remove border */
border: none;
+ /* 设置内边距 */
+ /* Set padding */
padding: 4px 80px;
+ /* 设置文本对齐方式 */
+ /* Set text alignment */
text-align: center;
+ /* 移除文本装饰 */
+ /* Remove text decoration */
text-decoration: none;
+ /* 设置为行内块元素 */
+ /* Set as inline-block element */
display: inline-block;
+ /* 设置字体大小 */
+ /* Set font size */
font-size: 16px;
+ /* 设置外边距 */
+ /* Set margin */
margin: 4px 2px;
}
\ No newline at end of file
diff --git a/src/collectedstatic/account/js/account.js b/src/collectedstatic/account/js/account.js
index f1a8771..08ae52f 100644
--- a/src/collectedstatic/account/js/account.js
+++ b/src/collectedstatic/account/js/account.js
@@ -1,15 +1,35 @@
+// 设置倒计时初始值为60秒
+// Set initial countdown value to 60 seconds
let wait = 60;
+// 倒计时函数,用于在发送验证码按钮上显示倒计时
+// Countdown function to display countdown on the send verification code button
function time(o) {
+ // 如果倒计时结束
+ // If countdown is over
if (wait == 0) {
+ // 移除按钮的禁用状态
+ // Remove button disabled state
o.removeAttribute("disabled");
+ // 恢复按钮文本
+ // Restore button text
o.value = "获取验证码";
+ // 重置倒计时
+ // Reset countdown
wait = 60
return false
} else {
+ // 设置按钮为禁用状态
+ // Set button to disabled state
o.setAttribute("disabled", true);
+ // 更新按钮文本显示倒计时
+ // Update button text to show countdown
o.value = "重新发送(" + wait + ")";
+ // 倒计时减1
+ // Decrease countdown by 1
wait--;
+ // 1秒后递归调用此函数
+ // Recursively call this function after 1 second
setTimeout(function () {
time(o)
},
@@ -17,31 +37,65 @@ function time(o) {
}
}
+// 获取验证码按钮点击事件处理
+// Verification code button click event handler
document.getElementById("btn").onclick = function () {
+ // 获取邮箱输入框元素
+ // Get email input element
let id_email = $("#id_email")
+ // 获取CSRF令牌
+ // Get CSRF token
let token = $("*[name='csrfmiddlewaretoken']").val()
+ // 获取当前按钮元素
+ // Get current button element
let ts = this
+ // 获取错误信息显示元素
+ // Get error message display element
let myErr = $("#myErr")
+ // 发送AJAX请求
+ // Send AJAX request
$.ajax(
{
+ // 请求URL
+ // Request URL
url: "/forget_password_code/",
+ // 请求类型
+ // Request type
type: "POST",
+ // 请求数据
+ // Request data
data: {
"email": id_email.val(),
"csrfmiddlewaretoken": token
},
+ // 请求成功回调函数
+ // Success callback function
success: function (result) {
+ // 如果返回结果不是"ok"
+ // If the returned result is not "ok"
if (result != "ok") {
+ // 移除旧的错误信息
+ // Remove old error message
myErr.remove()
+ // 在邮箱输入框后添加新的错误信息
+ // Add new error message after email input
id_email.after("
for (const p of from_box.parentNode.getElementsByTagName('p')) {
if (p.classList.contains("info")) {
- // Remove , because it just gets in the way.
+ // 移除 ,因为它会妨碍布局
from_box.parentNode.removeChild(p);
} else if (p.classList.contains("help")) {
- // Move help text up to the top so it isn't below the select
- // boxes or wrapped off on the side to the right of the add
- // button:
+ // 将帮助文本移到顶部,这样它就不会显示在选择框下方或添加按钮右侧
from_box.parentNode.insertBefore(p, from_box.parentNode.firstChild);
}
}
- //
")
return
}
+ // 移除错误信息
+ // Remove error message
myErr.remove()
+ // 启动倒计时
+ // Start countdown
time(ts)
},
+ // 请求失败回调函数
+ // Error callback function
error: function (e) {
+ // 弹出发送失败提示
+ // Show send failure alert
alert("发送失败,请重试")
}
}
);
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/autocomplete.css b/src/collectedstatic/admin/css/autocomplete.css
index 7478c2c..ef87959 100644
--- a/src/collectedstatic/admin/css/autocomplete.css
+++ b/src/collectedstatic/admin/css/autocomplete.css
@@ -1,54 +1,68 @@
+/* 管理界面自动补全样式 */
+/* Admin autocomplete styles */
+
+/* 选择器宽度设置 */
select.admin-autocomplete {
width: 20em;
}
+/* 自动补全容器最小高度设置 */
.select2-container--admin-autocomplete.select2-container {
min-height: 30px;
}
+/* 单选和多选容器最小高度设置 */
.select2-container--admin-autocomplete .select2-selection--single,
.select2-container--admin-autocomplete .select2-selection--multiple {
min-height: 30px;
padding: 0;
}
+/* 聚焦或打开状态下的选择器边框颜色 */
.select2-container--admin-autocomplete.select2-container--focus .select2-selection,
.select2-container--admin-autocomplete.select2-container--open .select2-selection {
border-color: var(--body-quiet-color);
min-height: 30px;
}
+/* 聚焦或打开状态下单选选择器内边距 */
.select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--single,
.select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--single {
padding: 0;
}
+/* 聚焦或打开状态下多选选择器内边距 */
.select2-container--admin-autocomplete.select2-container--focus .select2-selection.select2-selection--multiple,
.select2-container--admin-autocomplete.select2-container--open .select2-selection.select2-selection--multiple {
padding: 0;
}
+/* 单选选择器背景、边框和圆角设置 */
.select2-container--admin-autocomplete .select2-selection--single {
background-color: var(--body-bg);
border: 1px solid var(--border-color);
border-radius: 4px;
}
+/* 单选选择器渲染内容颜色和行高设置 */
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__rendered {
color: var(--body-fg);
line-height: 30px;
}
+/* 单选选择器清除按钮光标和浮动设置 */
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
}
+/* 单选选择器占位符颜色设置 */
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__placeholder {
color: var(--body-quiet-color);
}
+/* 单选选择器箭头高度、位置和宽度设置 */
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow {
height: 26px;
position: absolute;
@@ -57,6 +71,7 @@ select.admin-autocomplete {
width: 20px;
}
+/* 单选选择器箭头图标样式设置 */
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow b {
border-color: #888 transparent transparent transparent;
border-style: solid;
@@ -70,29 +85,35 @@ select.admin-autocomplete {
width: 0;
}
+/* 从右到左语言环境下单选选择器清除按钮浮动设置 */
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left;
}
+/* 从右到左语言环境下单选选择器箭头位置设置 */
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--single .select2-selection__arrow {
left: 1px;
right: auto;
}
+/* 禁用状态下单选选择器背景和光标设置 */
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single {
background-color: var(--darkened-bg);
cursor: default;
}
+/* 禁用状态下单选选择器清除按钮显示设置 */
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--single .select2-selection__clear {
display: none;
}
+/* 打开状态下单选选择器箭头图标样式设置 */
.select2-container--admin-autocomplete.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #888 transparent;
border-width: 0 4px 5px 4px;
}
+/* 多选选择器背景、边框、圆角和光标设置 */
.select2-container--admin-autocomplete .select2-selection--multiple {
background-color: var(--body-bg);
border: 1px solid var(--border-color);
@@ -100,6 +121,7 @@ select.admin-autocomplete {
cursor: text;
}
+/* 多选选择器渲染内容盒模型、列表样式、外边距、内边距和宽度设置 */
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered {
box-sizing: border-box;
list-style: none;
@@ -110,16 +132,19 @@ select.admin-autocomplete {
flex-wrap: wrap;
}
+/* 多选选择器渲染内容列表项样式设置 */
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__rendered li {
list-style: none;
}
+/* 多选选择器占位符颜色、上外边距和浮动设置 */
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__placeholder {
color: var(--body-quiet-color);
margin-top: 5px;
float: left;
}
+/* 多选选择器清除按钮光标、浮动、字体粗细、外边距、位置和右边距设置 */
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__clear {
cursor: pointer;
float: right;
@@ -129,6 +154,7 @@ select.admin-autocomplete {
right: 0;
}
+/* 多选选择器选项背景、边框、圆角、光标、浮动、右边距、上外边距和内边距设置 */
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice {
background-color: var(--darkened-bg);
border: 1px solid var(--border-color);
@@ -140,6 +166,7 @@ select.admin-autocomplete {
padding: 0 5px;
}
+/* 多选选择器选项移除按钮颜色、光标、显示、字体粗细和右边距设置 */
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove {
color: var(--body-quiet-color);
cursor: pointer;
@@ -148,52 +175,63 @@ select.admin-autocomplete {
margin-right: 2px;
}
+/* 多选选择器选项移除按钮悬停状态颜色设置 */
.select2-container--admin-autocomplete .select2-selection--multiple .select2-selection__choice__remove:hover {
color: var(--body-fg);
}
+/* 从右到左语言环境下多选选择器选项、占位符和内联搜索浮动设置 */
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-search--inline {
float: right;
}
+/* 从右到左语言环境下多选选择器选项左边距和右边距设置 */
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
margin-left: 5px;
margin-right: auto;
}
+/* 从右到左语言环境下多选选择器选项移除按钮左边距和右边距设置 */
.select2-container--admin-autocomplete[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto;
}
+/* 聚焦状态下多选选择器边框设置 */
.select2-container--admin-autocomplete.select2-container--focus .select2-selection--multiple {
border: solid var(--body-quiet-color) 1px;
outline: 0;
}
+/* 禁用状态下多选选择器背景和光标设置 */
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection--multiple {
background-color: var(--darkened-bg);
cursor: default;
}
+/* 禁用状态下多选选择器选项移除按钮显示设置 */
.select2-container--admin-autocomplete.select2-container--disabled .select2-selection__choice__remove {
display: none;
}
+/* 打开状态下选择器上边框圆角设置 */
.select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--above .select2-selection--multiple {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
+/* 打开状态下选择器下边框圆角设置 */
.select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--single, .select2-container--admin-autocomplete.select2-container--open.select2-container--below .select2-selection--multiple {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
+/* 下拉搜索框背景设置 */
.select2-container--admin-autocomplete .select2-search--dropdown {
background: var(--darkened-bg);
}
+/* 下拉搜索框字段背景、颜色、边框、圆角设置 */
.select2-container--admin-autocomplete .select2-search--dropdown .select2-search__field {
background: var(--body-bg);
color: var(--body-fg);
@@ -201,6 +239,7 @@ select.admin-autocomplete {
border-radius: 4px;
}
+/* 内联搜索框字段背景、颜色、边框、轮廓和外观设置 */
.select2-container--admin-autocomplete .select2-search--inline .select2-search__field {
background: transparent;
color: var(--body-fg);
@@ -210,6 +249,7 @@ select.admin-autocomplete {
-webkit-appearance: textfield;
}
+/* 结果选项最大高度、溢出和颜色设置 */
.select2-container--admin-autocomplete .select2-results > .select2-results__options {
max-height: 200px;
overflow-y: auto;
@@ -217,63 +257,76 @@ select.admin-autocomplete {
background: var(--body-bg);
}
+/* 分组结果选项内边距设置 */
.select2-container--admin-autocomplete .select2-results__option[role=group] {
padding: 0;
}
+/* 禁用结果选项颜色设置 */
.select2-container--admin-autocomplete .select2-results__option[aria-disabled=true] {
color: var(--body-quiet-color);
}
+/* 选中结果选项背景和颜色设置 */
.select2-container--admin-autocomplete .select2-results__option[aria-selected=true] {
background-color: var(--selected-bg);
color: var(--body-fg);
}
+/* 结果选项嵌套内边距设置 */
.select2-container--admin-autocomplete .select2-results__option .select2-results__option {
padding-left: 1em;
}
+/* 结果选项嵌套分组内边距设置 */
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__group {
padding-left: 0;
}
+/* 结果选项嵌套第二层内边距和左边距设置 */
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option {
margin-left: -1em;
padding-left: 2em;
}
+/* 结果选项嵌套第三层内边距和左边距设置 */
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -2em;
padding-left: 3em;
}
+/* 结果选项嵌套第四层内边距和左边距设置 */
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -3em;
padding-left: 4em;
}
+/* 结果选项嵌套第五层内边距和左边距设置 */
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -4em;
padding-left: 5em;
}
+/* 结果选项嵌套第六层内边距和左边距设置 */
.select2-container--admin-autocomplete .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -5em;
padding-left: 6em;
}
+/* 高亮结果选项背景和颜色设置 */
.select2-container--admin-autocomplete .select2-results__option--highlighted[aria-selected] {
background-color: var(--primary);
color: var(--primary-fg);
}
+/* 分组结果选项光标、显示、内边距设置 */
.select2-container--admin-autocomplete .select2-results__group {
cursor: default;
display: block;
padding: 6px;
}
+/* 错误状态下选择器边框设置 */
.errors .select2-selection {
border: 1px solid var(--error-fg);
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/base.css b/src/collectedstatic/admin/css/base.css
index 3791043..a713178 100644
--- a/src/collectedstatic/admin/css/base.css
+++ b/src/collectedstatic/admin/css/base.css
@@ -1,7 +1,9 @@
/*
+ DJANGO管理界面样式
DJANGO Admin styles
*/
+/* 变量定义 */
/* VARIABLE DEFINITIONS */
html[data-theme="light"],
:root {
@@ -38,8 +40,8 @@ html[data-theme="light"],
--message-warning-bg: #ffc;
--message-error-bg: #ffefef;
- --darkened-bg: #f8f8f8; /* A bit darker than --body-bg */
- --selected-bg: #e4e4e4; /* E.g. selected table cells */
+ --darkened-bg: #f8f8f8; /* 比 --body-bg 稍暗一点 */
+ --selected-bg: #e4e4e4; /* 例如选中的表格单元格 */
--selected-row: #ffc;
--button-fg: #fff;
@@ -102,6 +104,7 @@ body {
background: var(--body-bg);
}
+/* 链接 */
/* LINKS */
a:link, a:visited {
@@ -131,6 +134,7 @@ a.section:focus, a.section:hover {
text-decoration: underline;
}
+/* 全局默认样式 */
/* GLOBAL DEFAULTS */
p, ol, ul, dl {
@@ -260,6 +264,7 @@ hr {
line-height: 1px;
}
+/* 文本样式和修饰符 */
/* TEXT STYLES & MODIFIERS */
.small {
@@ -304,6 +309,7 @@ p img, h1 img, h2 img, h3 img, h4 img, td img {
display: none !important;
}
+/* 表格 */
/* TABLES */
table {
@@ -359,6 +365,7 @@ tr:nth-child(odd) + .row-form-errors .errorlist {
background: var(--darkened-bg);
}
+/* 可排序表格 */
/* SORTABLE TABLES */
thead th {
@@ -471,6 +478,7 @@ table thead th.sorted .sortoptions a.descending:hover {
background-position: 0 -70px;
}
+/* 表单默认样式 */
/* FORM DEFAULTS */
input, textarea, select, .form-row p, form .button {
@@ -490,8 +498,8 @@ textarea {
}
/*
-Minifiers remove the default (text) "type" attribute from "input" HTML tags.
-Add input:not([type]) to make the CSS stylesheet work the same.
+最小化器会从"input" HTML标签中移除默认的(文本)"type"属性。
+添加input:not([type])使CSS样式表保持相同效果。
*/
input:not([type]), input[type=text], input[type=password], input[type=email],
input[type=url], input[type=number], input[type=tel], textarea, select,
@@ -505,8 +513,8 @@ input[type=url], input[type=number], input[type=tel], textarea, select,
}
/*
-Minifiers remove the default (text) "type" attribute from "input" HTML tags.
-Add input:not([type]) to make the CSS stylesheet work the same.
+最小化器会从"input" HTML标签中移除默认的(文本)"type"属性。
+添加input:not([type])使CSS样式表保持相同效果。
*/
input:not([type]):focus, input[type=text]:focus, input[type=password]:focus,
input[type=email]:focus, input[type=url]:focus, input[type=number]:focus,
@@ -519,11 +527,12 @@ select {
}
select[multiple] {
- /* Allow HTML size attribute to override the height in the rule above. */
+ /* 允许HTML size属性覆盖上面的height规则 */
height: auto;
min-height: 150px;
}
+/* 表单按钮 */
/* FORM BUTTONS */
.button, input[type=submit], input[type=button], .submit-row input, a.button {
@@ -569,6 +578,7 @@ input[type=button][disabled].default {
}
+/* 模块 */
/* MODULES */
.module {
@@ -615,6 +625,7 @@ input[type=button][disabled].default {
border-collapse: collapse;
}
+/* 消息和错误 */
/* MESSAGES & ERRORS */
ul.messagelist {
@@ -711,6 +722,7 @@ td ul.errorlist + input, td ul.errorlist + select, td ul.errorlist + textarea {
padding: 5px 0 0 12px;
}
+/* 面包屑导航 */
/* BREADCRUMBS */
div.breadcrumbs {
@@ -729,6 +741,7 @@ div.breadcrumbs a:focus, div.breadcrumbs a:hover {
color: var(--breadcrumbs-fg);
}
+/* 操作图标 */
/* ACTION ICONS */
.viewlink, .inlineviewlink {
@@ -757,14 +770,15 @@ div.breadcrumbs a:focus, div.breadcrumbs a:hover {
}
a.deletelink:link, a.deletelink:visited {
- color: #CC3434; /* XXX Probably unused? */
+ color: #CC3434; /* XXX 可能未使用? */
}
a.deletelink:focus, a.deletelink:hover {
- color: #993333; /* XXX Probably unused? */
+ color: #993333; /* XXX 可能未使用? */
text-decoration: none;
}
+/* 对象工具 */
/* OBJECT TOOLS */
.object-tools {
@@ -821,6 +835,7 @@ a.deletelink:focus, a.deletelink:hover {
background-image: url(../img/tooltag-add.svg);
}
+/* 对象历史 */
/* OBJECT HISTORY */
#change-history table {
@@ -838,6 +853,7 @@ a.deletelink:focus, a.deletelink:hover {
overflow: hidden;
}
+/* 页面结构 */
/* PAGE STRUCTURE */
#container {
@@ -900,6 +916,7 @@ a.deletelink:focus, a.deletelink:hover {
}
}
+/* 列类型 */
/* COLUMN TYPES */
.colMS {
@@ -924,6 +941,7 @@ a.deletelink:focus, a.deletelink:hover {
width: auto;
}
+/* 头部 */
/* HEADER */
#header {
@@ -1019,6 +1037,7 @@ a.deletelink:focus, a.deletelink:hover {
margin-bottom: 1px;
}
+/* 侧边栏 */
/* SIDEBAR */
#content-related {
@@ -1095,6 +1114,7 @@ a.deletelink:focus, a.deletelink:hover {
background: var(--close-button-hover-bg);
}
+/* 弹窗 */
/* POPUP */
.popup #content {
padding: 20px;
@@ -1108,6 +1128,7 @@ a.deletelink:focus, a.deletelink:hover {
padding: 10px 20px;
}
+/* 分页器 */
/* PAGINATOR */
.paginator {
@@ -1177,4 +1198,4 @@ a.deletelink:focus, a.deletelink:hover {
border: 0;
color: var(--body-fg);
background-color: var(--body-bg);
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/changelists.css b/src/collectedstatic/admin/css/changelists.css
index 005b776..61aac6d 100644
--- a/src/collectedstatic/admin/css/changelists.css
+++ b/src/collectedstatic/admin/css/changelists.css
@@ -1,3 +1,4 @@
+/* 变更列表 */
/* CHANGELISTS */
#changelist {
@@ -50,6 +51,7 @@
overflow: hidden;
}
+/* 变更列表表格 */
/* CHANGELIST TABLES */
#changelist table thead th {
@@ -71,6 +73,7 @@
color: var(--body-quiet-color);
}
+/* 工具栏 */
/* TOOLBAR */
#toolbar {
@@ -129,6 +132,7 @@
word-break: break-word;
}
+/* 过滤器列 */
/* FILTER COLUMN */
#changelist-filter {
@@ -227,6 +231,7 @@
border-bottom: 1px solid var(--hairline-color);
}
+/* 日期钻取 */
/* DATE DRILLDOWN */
.change-list .toplinks {
@@ -250,6 +255,7 @@
color: var(--link-hover-color);
}
+/* 操作 */
/* ACTIONS */
.filtered .actions {
@@ -261,6 +267,7 @@
vertical-align: baseline;
}
+/* 一旦所有浏览器都支持:has()伪类,可以移除tr.selected选择器和添加该类的JS代码 */
/* Once the :has() pseudo-class is supported by all browsers, the tr.selected
selector and the JS adding the class can be removed. */
#changelist tbody tr.selected {
@@ -340,4 +347,4 @@
#changelist .actions .button:focus, #changelist .actions .button:hover {
border-color: var(--body-quiet-color);
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/dark_mode.css b/src/collectedstatic/admin/css/dark_mode.css
index 65b58d0..546583e 100644
--- a/src/collectedstatic/admin/css/dark_mode.css
+++ b/src/collectedstatic/admin/css/dark_mode.css
@@ -1,41 +1,93 @@
+/* 深色模式媒体查询,当系统偏好设置为深色时应用 */
+/* Dark mode media query, applied when system preference is set to dark */
@media (prefers-color-scheme: dark) {
:root {
+ /* 主色调 */
+ /* Primary color */
--primary: #264b5d;
+ /* 主要前景色 */
+ /* Primary foreground color */
--primary-fg: #f7f7f7;
+ /* 主体前景色 */
+ /* Body foreground color */
--body-fg: #eeeeee;
+ /* 主体背景色 */
+ /* Body background color */
--body-bg: #121212;
+ /* 主体安静色(较淡)*/
+ /* Body quiet color (lighter) */
--body-quiet-color: #d0d0d0;
+ /* 主体中等颜色 */
+ /* Body medium color */
--body-medium-color: #e0e0e0;
+ /* 主体响亮色(较亮)*/
+ /* Body loud color (brighter) */
--body-loud-color: #ffffff;
+ /* 面包屑链接颜色 */
+ /* Breadcrumbs link color */
--breadcrumbs-link-fg: #e0e0e0;
+ /* 面包屑背景色 */
+ /* Breadcrumbs background color */
--breadcrumbs-bg: var(--primary);
+ /* 链接颜色 */
+ /* Link color */
--link-fg: #81d4fa;
+ /* 链接悬停颜色 */
+ /* Link hover color */
--link-hover-color: #4ac1f7;
+ /* 链接选中颜色 */
+ /* Link selected color */
--link-selected-fg: #6f94c6;
+ /* 细线颜色 */
+ /* Hairline color */
--hairline-color: #272727;
+ /* 边框颜色 */
+ /* Border color */
--border-color: #353535;
+ /* 错误颜色 */
+ /* Error color */
--error-fg: #e35f5f;
+ /* 成功消息背景色 */
+ /* Success message background color */
--message-success-bg: #006b1b;
+ /* 警告消息背景色 */
+ /* Warning message background color */
--message-warning-bg: #583305;
+ /* 错误消息背景色 */
+ /* Error message background color */
--message-error-bg: #570808;
+ /* 深色背景 */
+ /* Darkened background */
--darkened-bg: #212121;
+ /* 选中背景色 */
+ /* Selected background color */
--selected-bg: #1b1b1b;
+ /* 选中行颜色 */
+ /* Selected row color */
--selected-row: #00363a;
+ /* 关闭按钮背景色 */
+ /* Close button background color */
--close-button-bg: #333333;
+ /* 关闭按钮悬停背景色 */
+ /* Close button hover background color */
--close-button-hover-bg: #666666;
+ /* 颜色方案设置为深色 */
+ /* Color scheme set to dark */
color-scheme: dark;
}
}
+/* 当HTML元素的data-theme属性为"dark"时应用的样式 */
+/* Styles applied when HTML element's data-theme attribute is "dark" */
html[data-theme="dark"] {
--primary: #264b5d;
--primary-fg: #f7f7f7;
@@ -71,25 +123,51 @@ html[data-theme="dark"] {
color-scheme: dark;
}
-/* THEME SWITCH */
+/* 主题切换按钮样式 */
+/* Theme switch button styles */
.theme-toggle {
+ /* 设置光标为指针 */
+ /* Set cursor to pointer */
cursor: pointer;
+ /* 移除边框 */
+ /* Remove border */
border: none;
+ /* 设置内边距为0 */
+ /* Set padding to 0 */
padding: 0;
+ /* 设置背景为透明 */
+ /* Set background to transparent */
background: transparent;
+ /* 设置垂直对齐方式 */
+ /* Set vertical alignment */
vertical-align: middle;
+ /* 设置左边距 */
+ /* Set left margin */
margin-inline-start: 5px;
+ /* 设置上边距 */
+ /* Set top margin */
margin-top: -1px;
}
+/* 主题切换按钮中的SVG图标样式 */
+/* SVG icon styles in theme toggle button */
.theme-toggle svg {
+ /* 设置垂直对齐方式 */
+ /* Set vertical alignment */
vertical-align: middle;
+ /* 设置高度 */
+ /* Set height */
height: 1.5rem;
+ /* 设置宽度 */
+ /* Set width */
width: 1.5rem;
+ /* 默认不显示 */
+ /* Hidden by default */
display: none;
}
/*
+完全隐藏屏幕阅读器文本,只显示匹配当前主题的文本。
Fully hide screen reader text so we only show the one matching the current
theme.
*/
@@ -97,19 +175,26 @@ theme.
display: none;
}
+/* 当data-theme属性为"auto"时显示自动主题标签 */
+/* Show auto theme label when data-theme attribute is "auto" */
html[data-theme="auto"] .theme-toggle .theme-label-when-auto {
display: block;
}
+/* 当data-theme属性为"dark"时显示深色主题标签 */
+/* Show dark theme label when data-theme attribute is "dark" */
html[data-theme="dark"] .theme-toggle .theme-label-when-dark {
display: block;
}
+/* 当data-theme属性为"light"时显示浅色主题标签 */
+/* Show light theme label when data-theme attribute is "light" */
html[data-theme="light"] .theme-toggle .theme-label-when-light {
display: block;
}
-/* ICONS */
+/* 图标样式 */
+/* Icon styles */
.theme-toggle svg.theme-icon-when-auto,
.theme-toggle svg.theme-icon-when-dark,
.theme-toggle svg.theme-icon-when-light {
@@ -117,14 +202,20 @@ html[data-theme="light"] .theme-toggle .theme-label-when-light {
color: var(--header-bg);
}
+/* 当data-theme属性为"auto"时显示自动主题图标 */
+/* Show auto theme icon when data-theme attribute is "auto" */
html[data-theme="auto"] .theme-toggle svg.theme-icon-when-auto {
display: block;
}
+/* 当data-theme属性为"dark"时显示深色主题图标 */
+/* Show dark theme icon when data-theme attribute is "dark" */
html[data-theme="dark"] .theme-toggle svg.theme-icon-when-dark {
display: block;
}
+/* 当data-theme属性为"light"时显示浅色主题图标 */
+/* Show light theme icon when data-theme attribute is "light" */
html[data-theme="light"] .theme-toggle svg.theme-icon-when-light {
display: block;
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/dashboard.css b/src/collectedstatic/admin/css/dashboard.css
index 242b81a..90a1f8b 100644
--- a/src/collectedstatic/admin/css/dashboard.css
+++ b/src/collectedstatic/admin/css/dashboard.css
@@ -1,3 +1,4 @@
+/* 仪表板 */
/* DASHBOARD */
.dashboard td, .dashboard th {
word-break: break-word;
@@ -16,6 +17,7 @@
padding-right: .6em;
}
+/* 最近操作模块 */
/* RECENT ACTIONS MODULE */
.module ul.actionlist {
@@ -26,4 +28,4 @@ ul.actionlist li {
list-style-type: none;
overflow: hidden;
text-overflow: ellipsis;
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/forms.css b/src/collectedstatic/admin/css/forms.css
index c6ce788..23bf5db 100644
--- a/src/collectedstatic/admin/css/forms.css
+++ b/src/collectedstatic/admin/css/forms.css
@@ -1,5 +1,7 @@
+/* 导入小部件样式 */
@import url('widgets.css');
+/* 表单行 */
/* FORM ROWS */
.form-row {
@@ -34,6 +36,7 @@ form .form-row p {
padding-bottom: 10px;
}
+/* 表单标签 */
/* FORM LABELS */
label {
@@ -46,6 +49,7 @@ label {
font-weight: bold;
}
+/* 单选按钮 */
/* RADIO BUTTONS */
form div.radiolist div {
@@ -75,6 +79,7 @@ form ul.inline li {
padding-right: 7px;
}
+/* 字段集 */
/* FIELDSETS */
fieldset .fieldset-heading,
@@ -89,6 +94,7 @@ fieldset .inline-heading,
color: var(--header-link-color);
}
+/* 对齐的字段集 */
/* ALIGNED FIELDSETS */
.aligned label {
@@ -199,6 +205,7 @@ fieldset .fieldBox {
margin-right: 20px;
}
+/* 宽字段集 */
/* WIDE FIELDSETS */
.wide label {
@@ -220,6 +227,7 @@ form div.help ul {
width: 450px;
}
+/* 可折叠字段集 */
/* COLLAPSIBLE FIELDSETS */
.collapse summary .fieldset-heading,
@@ -232,12 +240,14 @@ form div.help ul {
padding: 0;
}
+/* 等宽字体文本区域 */
/* MONOSPACE TEXTAREAS */
fieldset.monospace textarea {
font-family: var(--font-family-monospace);
}
+/* 提交行 */
/* SUBMIT ROW */
.submit-row {
@@ -307,6 +317,7 @@ body.popup .submit-row {
text-decoration: none;
}
+/* 自定义表单字段 */
/* CUSTOM FORM FIELDS */
.vSelectMultipleField {
@@ -362,6 +373,7 @@ body.popup .submit-row {
width: 20em;
}
+/* 行内组 */
/* INLINES */
.inline-group {
@@ -471,6 +483,7 @@ body.popup .submit-row {
display: none;
}
+/* 相关字段添加一个/查找 */
/* RELATED FIELD ADD ONE / LOOKUP */
.related-lookup {
@@ -495,4 +508,4 @@ form .related-widget-wrapper ul {
.clearable-file-input input {
margin-top: 0;
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/login.css b/src/collectedstatic/admin/css/login.css
index 805a34b..84bb072 100644
--- a/src/collectedstatic/admin/css/login.css
+++ b/src/collectedstatic/admin/css/login.css
@@ -1,61 +1,89 @@
+/* 登录表单样式 */
/* LOGIN FORM */
.login {
+ /* 设置背景色 */
background: var(--darkened-bg);
+ /* 设置高度为自动 */
height: auto;
}
.login #header {
+ /* 设置头部高度为自动 */
height: auto;
+ /* 设置内边距 */
padding: 15px 16px;
+ /* 设置内容居中对齐 */
justify-content: center;
}
.login #header h1 {
+ /* 设置标题字体大小 */
font-size: 1.125rem;
+ /* 设置外边距 */
margin: 0;
}
.login #header h1 a {
+ /* 设置链接颜色 */
color: var(--header-link-color);
}
.login #content {
+ /* 设置内容区内边距 */
padding: 20px;
}
.login #container {
+ /* 设置容器背景色 */
background: var(--body-bg);
+ /* 设置边框 */
border: 1px solid var(--hairline-color);
+ /* 设置圆角 */
border-radius: 4px;
+ /* 设置溢出隐藏 */
overflow: hidden;
+ /* 设置宽度 */
width: 28em;
+ /* 设置最小宽度 */
min-width: 300px;
+ /* 设置外边距居中 */
margin: 100px auto;
+ /* 设置高度为自动 */
height: auto;
}
.login .form-row {
+ /* 设置表单行内边距 */
padding: 4px 0;
}
.login .form-row label {
+ /* 设置标签为块级元素 */
display: block;
+ /* 设置行高 */
line-height: 2em;
}
.login .form-row #id_username, .login .form-row #id_password {
+ /* 设置内边距 */
padding: 8px;
+ /* 设置宽度为100% */
width: 100%;
+ /* 设置盒模型为border-box */
box-sizing: border-box;
}
.login .submit-row {
+ /* 设置提交行内边距 */
padding: 1em 0 0 0;
+ /* 设置外边距 */
margin: 0;
+ /* 设置文本居中对齐 */
text-align: center;
}
.login .password-reset-link {
+ /* 设置密码重置链接文本居中对齐 */
text-align: center;
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/nav_sidebar.css b/src/collectedstatic/admin/css/nav_sidebar.css
index 7eb0de9..9ff6dc7 100644
--- a/src/collectedstatic/admin/css/nav_sidebar.css
+++ b/src/collectedstatic/admin/css/nav_sidebar.css
@@ -1,9 +1,13 @@
+/* 粘性定位 - 使侧边栏在滚动时保持在顶部 */
+/* sticky */
.sticky {
position: sticky;
top: 0;
max-height: 100vh;
}
+/* 切换导航侧边栏按钮 */
+/* 切换导航侧边栏按钮 */
.toggle-nav-sidebar {
z-index: 20;
left: 0;
@@ -21,16 +25,19 @@
padding: 0;
}
+/* 从右到左语言环境下的切换按钮边框调整 */
[dir="rtl"] .toggle-nav-sidebar {
border-left: 1px solid var(--hairline-color);
border-right: 0;
}
+/* 切换按钮的悬停和焦点状态 */
.toggle-nav-sidebar:hover,
.toggle-nav-sidebar:focus {
background-color: var(--darkened-bg);
}
+/* 导航侧边栏 */
#nav-sidebar {
z-index: 15;
flex: 0 0 275px;
@@ -42,6 +49,7 @@
overflow: auto;
}
+/* 从右到左语言环境下的导航侧边栏调整 */
[dir="rtl"] #nav-sidebar {
border-left: 1px solid var(--hairline-color);
border-right: 0;
@@ -51,82 +59,99 @@
margin-right: -276px;
}
+/* 切换导航侧边栏按钮的:before伪元素内容 */
.toggle-nav-sidebar::before {
content: '\00BB';
}
+/* 主内容区域移动时切换按钮的:before伪元素内容 */
.main.shifted .toggle-nav-sidebar::before {
content: '\00AB';
}
+/* 主内容区域的导航侧边栏可见性 */
.main > #nav-sidebar {
visibility: hidden;
}
+/* 主内容区域移动时导航侧边栏的可见性 */
.main.shifted > #nav-sidebar {
margin-left: 0;
visibility: visible;
}
+/* 从右到左语言环境下主内容区域移动时导航侧边栏的右边距 */
[dir="rtl"] .main.shifted > #nav-sidebar {
margin-right: 0;
}
+/* 导航侧边栏模块标题的宽度和换行处理 */
#nav-sidebar .module th {
width: 100%;
overflow-wrap: anywhere;
}
+/* 导航侧边栏模块标题和说明文字的内边距 */
#nav-sidebar .module th,
#nav-sidebar .module caption {
padding-left: 16px;
}
+/* 导航侧边栏模块数据单元格的空白处理 */
#nav-sidebar .module td {
white-space: nowrap;
}
+/* 从右到左语言环境下导航侧边栏模块标题和说明文字的内边距调整 */
[dir="rtl"] #nav-sidebar .module th,
[dir="rtl"] #nav-sidebar .module caption {
padding-left: 8px;
padding-right: 16px;
}
+/* 当前应用的节链接样式 */
#nav-sidebar .current-app .section:link,
#nav-sidebar .current-app .section:visited {
color: var(--header-color);
font-weight: bold;
}
+/* 当前模型的背景色 */
#nav-sidebar .current-model {
background: var(--selected-row);
}
+/* 强制颜色模式下当前模型的背景色 */
@media (forced-colors: active) {
#nav-sidebar .current-model {
background-color: SelectedItem;
}
}
+/* 主内容区域导航侧边栏和内容的最大宽度 */
.main > #nav-sidebar + .content {
max-width: calc(100% - 23px);
}
+/* 主内容区域移动时导航侧边栏和内容的最大宽度 */
.main.shifted > #nav-sidebar + .content {
max-width: calc(100% - 299px);
}
+/* 移动设备样式 - 隐藏导航侧边栏和切换按钮 */
@media (max-width: 767px) {
#nav-sidebar, #toggle-nav-sidebar {
display: none;
}
+ /* 移动设备上主内容区域的最大宽度 */
.main > #nav-sidebar + .content,
.main.shifted > #nav-sidebar + .content {
max-width: 100%;
}
}
+/* 导航过滤器输入框样式 */
#nav-filter {
width: 100%;
box-sizing: border-box;
@@ -137,14 +162,17 @@
color: var(--body-fg);
}
+/* 导航过滤器输入框的焦点状态 */
#nav-filter:focus {
border-color: var(--body-quiet-color);
}
+/* 导航过滤器无结果时的背景色 */
#nav-filter.no-results {
background: var(--message-error-bg);
}
+/* 导航侧边栏表格宽度 */
#nav-sidebar table {
width: 100%;
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/responsive.css b/src/collectedstatic/admin/css/responsive.css
index f0fcade..6b606ab 100644
--- a/src/collectedstatic/admin/css/responsive.css
+++ b/src/collectedstatic/admin/css/responsive.css
@@ -1,3 +1,4 @@
+/* 平板设备 */
/* Tablets */
input[type="submit"], button {
@@ -6,6 +7,7 @@ input[type="submit"], button {
}
@media (max-width: 1024px) {
+ /* 基础样式 */
/* Basic */
html {
@@ -21,6 +23,7 @@ input[type="submit"], button {
font-size: 0.75rem;
}
+ /* 布局 */
/* Layout */
#container {
@@ -35,6 +38,7 @@ input[type="submit"], button {
padding: 10px 30px;
}
+ /* 头部 */
/* Header */
#header {
@@ -60,6 +64,7 @@ input[type="submit"], button {
line-height: 1.4;
}
+ /* 仪表板 */
/* Dashboard */
.dashboard #content {
@@ -90,6 +95,7 @@ input[type="submit"], button {
font-size: 0.8125rem;
}
+ /* 变更列表 */
/* Changelist */
#toolbar {
@@ -168,6 +174,7 @@ input[type="submit"], button {
border-top: none;
}
+ /* 表单 */
/* Forms */
label {
@@ -175,8 +182,8 @@ input[type="submit"], button {
}
/*
- Minifiers remove the default (text) "type" attribute from "input" HTML
- tags. Add input:not([type]) to make the CSS stylesheet work the same.
+ 最小化器会从"input" HTML标签中移除默认的(文本)"type"属性。
+ 添加input:not([type])使CSS样式表保持相同效果。
*/
.form-row input:not([type]),
.form-row input[type=text],
@@ -242,6 +249,7 @@ input[type="submit"], button {
padding: 7px;
}
+ /* 选择器 */
/* Selector */
.selector {
@@ -334,6 +342,7 @@ input[type="submit"], button {
overflow: auto;
}
+ /* 消息 */
/* Messages */
ul.messagelist li {
@@ -349,6 +358,7 @@ input[type="submit"], button {
background-position: 30px 14px;
}
+ /* 登录 */
/* Login */
.login #header {
@@ -371,6 +381,7 @@ input[type="submit"], button {
margin-top: 10px;
}
+ /* 文档 */
/* Docs */
.module table.xfull {
@@ -382,9 +393,11 @@ input[type="submit"], button {
}
}
+/* 移动设备 */
/* Mobile */
@media (max-width: 767px) {
+ /* 布局 */
/* Layout */
#header, #content {
@@ -395,6 +408,7 @@ input[type="submit"], button {
padding: 10px 15px;
}
+ /* 仪表板 */
/* Dashboard */
.colMS, .colSM {
@@ -415,6 +429,7 @@ input[type="submit"], button {
font-size: 1rem;
}
+ /* 变更列表 */
/* Changelist */
#changelist {
@@ -465,6 +480,7 @@ input[type="submit"], button {
margin-left: 15px;
}
+ /* 表单 */
/* Forms */
.form-row {
@@ -575,6 +591,7 @@ input[type="submit"], button {
margin-top: 5px;
}
+ /* 相关小部件 */
/* Related widget */
.related-widget-wrapper {
@@ -600,6 +617,7 @@ input[type="submit"], button {
align-self: center;
}
+ /* 选择器 */
/* Selector */
.selector {
@@ -643,6 +661,7 @@ input[type="submit"], button {
background-position: 0 -72px;
}
+ /* 行内组 */
/* Inlines */
.inline-group[data-inline-type="stacked"] .inline-related {
@@ -714,6 +733,7 @@ input[type="submit"], button {
background-position: 8px 9px;
}
+ /* 提交行 */
/* Submit row */
.submit-row {
@@ -736,6 +756,7 @@ input[type="submit"], button {
margin: 0;
}
+ /* 消息 */
/* Messages */
ul.messagelist li {
@@ -751,12 +772,14 @@ input[type="submit"], button {
background-position: 15px 14px;
}
+ /* 分页器 */
/* Paginator */
.paginator .this-page, .paginator a:link, .paginator a:visited {
padding: 4px 10px;
}
+ /* 登录 */
/* Login */
body.login {
@@ -810,6 +833,7 @@ input[type="submit"], button {
font-size: 0.8125rem;
}
+ /* 日历和时钟 */
/* Calendar and clock */
.calendarbox, .clockbox {
@@ -884,6 +908,7 @@ input[type="submit"], button {
top: 10px;
}
+ /* 历史记录 */
/* History */
table#change-history tbody th, table#change-history tbody td {
@@ -895,10 +920,11 @@ input[type="submit"], button {
width: auto;
}
+ /* 文档 */
/* Docs */
table.model tbody th, table.model tbody td {
font-size: 0.8125rem;
word-break: break-word;
}
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/responsive_rtl.css b/src/collectedstatic/admin/css/responsive_rtl.css
index 5e8f5c5..eff7623 100644
--- a/src/collectedstatic/admin/css/responsive_rtl.css
+++ b/src/collectedstatic/admin/css/responsive_rtl.css
@@ -1,24 +1,30 @@
+/* 平板设备样式 */
/* TABLETS */
@media (max-width: 1024px) {
+ /* 从右到左的语言布局调整 */
[dir="rtl"] .colMS {
margin-right: 0;
}
+ /* 用户工具栏文本对齐调整 */
[dir="rtl"] #user-tools {
text-align: right;
}
+ /* 变更列表操作标签内边距调整 */
[dir="rtl"] #changelist .actions label {
padding-left: 10px;
padding-right: 0;
}
+ /* 变更列表操作选择框边距调整 */
[dir="rtl"] #changelist .actions select {
margin-left: 0;
margin-right: 15px;
}
+ /* 过滤器相关元素的边距调整 */
[dir="rtl"] .change-list .filtered .results,
[dir="rtl"] .change-list .filtered .paginator,
[dir="rtl"] .filtered #toolbar,
@@ -28,62 +34,76 @@
margin-left: 0;
}
+ /* 行内组添加行链接的内边距和背景位置调整 */
[dir="rtl"] .inline-group div.add-row a,
[dir="rtl"] .inline-group .tabular tr.add-row td a {
padding: 8px 26px 8px 10px;
background-position: calc(100% - 8px) 9px;
}
+ /* 对象工具列表项浮动方向调整 */
[dir="rtl"] .object-tools li {
float: right;
}
+ /* 对象工具相邻列表项的边距调整 */
[dir="rtl"] .object-tools li + li {
margin-left: 0;
margin-right: 15px;
}
+ /* 仪表板模块表格链接内边距调整 */
[dir="rtl"] .dashboard .module table td a {
padding-left: 0;
padding-right: 16px;
}
}
+/* 移动设备样式 */
/* MOBILE */
@media (max-width: 767px) {
+ /* 相关查找和日期时间快捷方式的边距调整 */
[dir="rtl"] .aligned .related-lookup,
[dir="rtl"] .aligned .datetimeshortcuts {
margin-left: 0;
margin-right: 15px;
}
+ /* 列表的右边距调整 */
[dir="rtl"] .aligned ul,
[dir="rtl"] form .aligned ul.errorlist {
margin-right: 0;
}
+ /* 变更列表过滤器的边距调整 */
[dir="rtl"] #changelist-filter {
margin-left: 0;
margin-right: 0;
}
+
+ /* 复选框标签的内边距调整 */
[dir="rtl"] .aligned .vCheckboxLabel {
padding: 1px 5px 0 0;
}
+ /* 选择器移除按钮的背景位置调整 */
[dir="rtl"] .selector-remove {
background-position: 0 0;
}
+ /* 选择器移除按钮的焦点和悬停状态背景位置调整 */
[dir="rtl"] :enabled.selector-remove:focus, :enabled.selector-remove:hover {
background-position: 0 -24px;
}
+ /* 选择器添加按钮的背景位置调整 */
[dir="rtl"] .selector-add {
background-position: 0 -48px;
}
+ /* 选择器添加按钮的焦点和悬停状态背景位置调整 */
[dir="rtl"] :enabled.selector-add:focus, :enabled.selector-add:hover {
background-position: 0 -72px;
}
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/rtl.css b/src/collectedstatic/admin/css/rtl.css
index a2556d0..0582d7c 100644
--- a/src/collectedstatic/admin/css/rtl.css
+++ b/src/collectedstatic/admin/css/rtl.css
@@ -1,91 +1,113 @@
+/* 全局样式 - 适用于从右到左的语言 */
/* GLOBAL */
+/* 表格标题文本对齐 */
th {
text-align: right;
}
+/* 模块标题和说明文字对齐 */
.module h2, .module caption {
text-align: right;
}
+/* 模块列表的左右边距调整 */
.module ul, .module ol {
margin-left: 0;
margin-right: 1.5em;
}
+/* 查看、添加、变更、隐藏链接的内边距和背景位置调整 */
.viewlink, .addlink, .changelink, .hidelink {
padding-left: 0;
padding-right: 16px;
background-position: 100% 1px;
}
+/* 删除链接的内边距和背景位置调整 */
.deletelink {
padding-left: 0;
padding-right: 16px;
background-position: 100% 1px;
}
+/* 对象工具栏浮动方向 */
.object-tools {
float: left;
}
+/* 表格首列的边框调整 */
thead th:first-child,
tfoot td:first-child {
border-left: none;
}
+/* 布局相关样式 */
/* LAYOUT */
+/* 用户工具栏位置和文本对齐调整 */
#user-tools {
right: auto;
left: 0;
text-align: left;
}
+/* 面包屑导航文本对齐 */
div.breadcrumbs {
text-align: right;
}
+/* 主内容区域浮动方向 */
#content-main {
float: right;
}
+/* 相关内容区域浮动方向和边距调整 */
#content-related {
float: left;
margin-left: -300px;
margin-right: auto;
}
+/* 主列和侧边栏布局调整 */
.colMS {
margin-left: 300px;
margin-right: 0;
}
+/* 可排序表格样式 */
/* SORTABLE TABLES */
+/* 排序选项浮动方向 */
table thead th.sorted .sortoptions {
float: left;
}
+/* 已排序列文本内边距调整 */
thead th.sorted .text {
padding-right: 0;
padding-left: 42px;
}
+/* 仪表板样式 */
/* dashboard styles */
+/* 仪表板模块表格链接内边距调整 */
.dashboard .module table td a {
padding-left: .6em;
padding-right: 16px;
}
+/* 变更列表样式 */
/* changelists styles */
+/* 过滤变更列表的表格边框调整 */
.change-list .filtered table {
border-left: none;
border-right: 0px none;
}
+/* 变更列表过滤器边框和边距调整 */
#changelist-filter {
border-left: none;
border-right: none;
@@ -93,6 +115,7 @@ thead th.sorted .text {
margin-right: 30px;
}
+/* 已选过滤条件的边框、内边距和边距调整 */
#changelist-filter li.selected {
border-left: none;
padding-left: 10px;
@@ -102,40 +125,49 @@ thead th.sorted .text {
margin-right: -15px;
}
+/* 变更列表表格首列的边框调整 */
#changelist table tbody td:first-child, #changelist table tbody th:first-child {
border-right: none;
border-left: none;
}
+/* 分页器末页链接的边距调整 */
.paginator .end {
margin-left: 6px;
margin-right: 0;
}
+/* 分页器输入框的边距调整 */
.paginator input {
margin-left: 0;
margin-right: auto;
}
+/* 表单样式 */
/* FORMS */
+/* 对齐标签的内边距调整 */
.aligned label {
padding: 0 0 3px 1em;
}
+/* 删除链接的边距调整 */
.submit-row a.deletelink {
margin-left: 0;
margin-right: auto;
}
+/* 日期和时间字段的边距调整 */
.vDateField, .vTimeField {
margin-left: 2px;
}
+/* 对齐表单行输入框的边距调整 */
.aligned .form-row input {
margin-left: 5px;
}
+/* 对齐列表的边距和内边距调整 */
form .aligned ul {
margin-right: 163px;
padding-right: 10px;
@@ -143,12 +175,14 @@ form .aligned ul {
padding-left: 0;
}
+/* 行内列表项的浮动方向和内边距调整 */
form ul.inline li {
float: right;
padding-right: 0;
padding-left: 7px;
}
+/* 表单帮助文本的边距和内边距调整 */
form .aligned p.help,
form .aligned div.help {
margin-left: 0;
@@ -156,6 +190,7 @@ form .aligned div.help {
padding-right: 10px;
}
+/* 帮助文本列表、复选框行和时区警告的边距调整 */
form div.help ul,
form .aligned .checkbox-row + .help,
form .aligned p.date div.help.timezonewarning,
@@ -165,6 +200,7 @@ form .aligned p.time div.help.timezonewarning {
padding-right: 0;
}
+/* 宽表单帮助文本、错误列表和帮助文本的内边距调整 */
form .wide p.help,
form .wide ul.errorlist,
form .wide div.help {
@@ -172,27 +208,33 @@ form .wide div.help {
padding-right: 50px;
}
+/* 提交行文本对齐 */
.submit-row {
text-align: right;
}
+/* 字段框的边距调整 */
fieldset .fieldBox {
margin-left: 20px;
margin-right: 0;
}
+/* 错误列表项的背景位置和内边距调整 */
.errorlist li {
background-position: 100% 12px;
padding: 0;
}
+/* 错误提示的背景位置和内边距调整 */
.errornote {
background-position: 100% 12px;
padding: 10px 12px;
}
+/* 小部件样式 */
/* WIDGETS */
+/* 日历导航上一个按钮的位置和背景调整 */
.calendarnav-previous {
top: 0;
left: auto;
@@ -200,6 +242,7 @@ fieldset .fieldBox {
background: url(../img/calendar-icons.svg) 0 -15px no-repeat;
}
+/* 日历导航下一个按钮的位置和背景调整 */
.calendarnav-next {
top: 0;
right: auto;
@@ -207,70 +250,87 @@ fieldset .fieldBox {
background: url(../img/calendar-icons.svg) 0 0 no-repeat;
}
+/* 日历标题和日历框标题文本对齐 */
.calendar caption, .calendarbox h2 {
text-align: center;
}
+/* 选择器浮动方向 */
.selector {
float: right;
}
+/* 选择器过滤器文本对齐 */
.selector .selector-filter {
text-align: right;
}
+/* 选择器添加按钮的背景和背景大小调整 */
.selector-add {
background: url(../img/selector-icons.svg) 0 -96px no-repeat;
background-size: 24px auto;
}
+/* 选择器添加按钮的焦点和悬停状态背景位置调整 */
:enabled.selector-add:focus, :enabled.selector-add:hover {
background-position: 0 -120px;
}
+/* 选择器移除按钮的背景和背景大小调整 */
.selector-remove {
background: url(../img/selector-icons.svg) 0 -144px no-repeat;
background-size: 24px auto;
}
+/* 选择器移除按钮的焦点和悬停状态背景位置调整 */
:enabled.selector-remove:focus, :enabled.selector-remove:hover {
background-position: 0 -168px;
}
+/* 全选按钮的背景调整 */
.selector-chooseall {
background: url(../img/selector-icons.svg) right -128px no-repeat;
}
+/* 全选按钮的焦点和悬停状态背景位置调整 */
:enabled.selector-chooseall:focus, :enabled.selector-chooseall:hover {
background-position: 100% -144px;
}
+/* 全清按钮的背景调整 */
.selector-clearall {
background: url(../img/selector-icons.svg) 0 -160px no-repeat;
}
+/* 全清按钮的焦点和悬停状态背景位置调整 */
:enabled.selector-clearall:focus, :enabled.selector-clearall:hover {
background-position: 0 -176px;
}
+/* 行内删除链接浮动方向 */
.inline-deletelink {
float: left;
}
+/* 日期时间表单行的溢出处理 */
form .form-row p.datetime {
overflow: hidden;
}
+/* 相关小部件包装器的浮动方向 */
.related-widget-wrapper {
float: right;
}
+/* 其他样式 */
/* MISC */
+/* 行内相关标题和行内组标题文本对齐 */
.inline-related h2, .inline-group h2 {
text-align: right
}
+/* 行内相关标题删除链接的内边距、位置和浮动方向调整 */
.inline-related h3 span.delete {
padding-right: 20px;
padding-left: inherit;
@@ -279,15 +339,18 @@ form .form-row p.datetime {
float:left;
}
+/* 行内相关标题删除链接标签的边距调整 */
.inline-related h3 span.delete label {
margin-left: inherit;
margin-right: 2px;
}
+/* 行内组表格原始列段落的右边距调整 */
.inline-group .tabular td.original p {
right: 0;
}
+/* 选择器选择器的边距调整 */
.selector .selector-chooser {
margin: 0;
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/unusable_password_field.css b/src/collectedstatic/admin/css/unusable_password_field.css
index d46eb03..1bfa9ea 100644
--- a/src/collectedstatic/admin/css/unusable_password_field.css
+++ b/src/collectedstatic/admin/css/unusable_password_field.css
@@ -1,14 +1,17 @@
+/* 当用户选择可用密码时隐藏警告字段 */
/* Hide warnings fields if usable password is selected */
form:has(#id_usable_password input[value="true"]:checked) .messagelist {
display: none;
}
+/* 当用户选择不可用密码时隐藏密码字段 */
/* Hide password fields if unusable password is selected */
form:has(#id_usable_password input[value="false"]:checked) .field-password1,
form:has(#id_usable_password input[value="false"]:checked) .field-password2 {
display: none;
}
+/* 选择适当的提交按钮 */
/* Select appropriate submit button */
form:has(#id_usable_password input[value="true"]:checked) input[type="submit"].unset-password {
display: none;
@@ -16,4 +19,4 @@ form:has(#id_usable_password input[value="true"]:checked) input[type="submit"].u
form:has(#id_usable_password input[value="false"]:checked) input[type="submit"].set-password {
display: none;
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/vendor/select2/select2.min.css b/src/collectedstatic/admin/css/vendor/select2/select2.min.css
index 7c18ad5..29d27bd 100644
--- a/src/collectedstatic/admin/css/vendor/select2/select2.min.css
+++ b/src/collectedstatic/admin/css/vendor/select2/select2.min.css
@@ -1 +1,3 @@
-.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb}
+/* 这是Select2插件的压缩CSS样式文件 */
+/* This is the minified CSS file for the Select2 plugin */
+.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;-webkit-clip-path:inset(50%) !important;clip-path:inset(50%) !important;height:1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important;white-space:nowrap !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px;padding:1px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right;margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/css/widgets.css b/src/collectedstatic/admin/css/widgets.css
index 538af2e..92fa79f 100644
--- a/src/collectedstatic/admin/css/widgets.css
+++ b/src/collectedstatic/admin/css/widgets.css
@@ -1,3 +1,4 @@
+/* 选择器(过滤器界面)*/
/* SELECTOR (FILTER INTERFACE) */
.selector {
@@ -207,6 +208,7 @@
background-position: 0 -144px;
}
+/* 堆叠选择器 */
/* STACKED SELECTORS */
.stacked {
@@ -303,6 +305,7 @@
width: 1.125rem;
}
+/* 日期和时间 */
/* DATE AND TIME */
p.datetime {
@@ -381,6 +384,7 @@ p.url {
font-weight: normal;
}
+/* 文件上传 */
/* FILE UPLOADS */
p.file-upload {
@@ -407,6 +411,7 @@ span.clearable-file-input label {
float: none;
}
+/* 日历和时钟 */
/* CALENDARS & CLOCKS */
.calendarbox, .clockbox {
@@ -571,6 +576,7 @@ ul.timelist, .timelist li {
padding: 2px;
}
+/* 行内编辑 */
/* EDIT INLINE */
.inline-deletelink {
@@ -587,6 +593,7 @@ ul.timelist, .timelist li {
cursor: pointer;
}
+/* 相关小部件包装器 */
/* RELATED WIDGET WRAPPER */
.related-widget-wrapper {
display: flex;
@@ -606,8 +613,9 @@ ul.timelist, .timelist li {
filter: grayscale(0);
}
+/* GIS地图 */
/* GIS MAPS */
.dj_map {
width: 600px;
height: 400px;
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/SelectBox.js b/src/collectedstatic/admin/js/SelectBox.js
index 3db4ec7..86e300d 100644
--- a/src/collectedstatic/admin/js/SelectBox.js
+++ b/src/collectedstatic/admin/js/SelectBox.js
@@ -1,66 +1,111 @@
'use strict';
{
const SelectBox = {
- cache: {},
+ cache: {}, // 选择框缓存,用于存储选项数据
+
+ /**
+ * 初始化选择框缓存
+ * @param {string} id - 选择框元素的ID
+ */
init: function(id) {
const box = document.getElementById(id);
SelectBox.cache[id] = [];
const cache = SelectBox.cache[id];
+ // 将选择框中的所有选项添加到缓存中
for (const node of box.options) {
cache.push({value: node.value, text: node.text, displayed: 1});
}
},
+
+ /**
+ * 从缓存重新显示HTML选择框
+ * @param {string} id - 选择框元素的ID
+ */
redisplay: function(id) {
- // Repopulate HTML select box from cache
+ // 从缓存重新填充HTML选择框
const box = document.getElementById(id);
const scroll_value_from_top = box.scrollTop;
box.innerHTML = '';
+ // 只显示标记为displayed的选项
for (const node of SelectBox.cache[id]) {
if (node.displayed) {
const new_option = new Option(node.text, node.value, false, false);
- // Shows a tooltip when hovering over the option
+ // 鼠标悬停时显示提示工具
new_option.title = node.text;
box.appendChild(new_option);
}
}
box.scrollTop = scroll_value_from_top;
},
+
+ /**
+ * 根据文本过滤选择框中的选项
+ * @param {string} id - 选择框元素的ID
+ * @param {string} text - 过滤文本
+ */
filter: function(id, text) {
- // Redisplay the HTML select box, displaying only the choices containing ALL
- // the words in text. (It's an AND search.)
+ // 重新显示HTML选择框,仅显示包含文本中所有单词的选项(AND搜索)
const tokens = text.toLowerCase().split(/\s+/);
for (const node of SelectBox.cache[id]) {
node.displayed = 1;
const node_text = node.text.toLowerCase();
+ // 检查每个词是否都包含在选项文本中
for (const token of tokens) {
if (!node_text.includes(token)) {
node.displayed = 0;
- break; // Once the first token isn't found we're done
+ break; // 一旦第一个词未找到就结束
}
}
}
SelectBox.redisplay(id);
},
+
+ /**
+ * 获取隐藏节点数量
+ * @param {string} id - 选择框元素的ID
+ * @returns {number} 隐藏节点的数量
+ */
get_hidden_node_count(id) {
const cache = SelectBox.cache[id] || [];
return cache.filter(node => node.displayed === 0).length;
},
+
+ /**
+ * 从缓存中删除指定值的选项
+ * @param {string} id - 选择框元素的ID
+ * @param {string} value - 要删除的选项值
+ */
delete_from_cache: function(id, value) {
let delete_index = null;
const cache = SelectBox.cache[id];
+ // 查找要删除的选项索引
for (const [i, node] of cache.entries()) {
if (node.value === value) {
delete_index = i;
break;
}
}
+ // 从缓存中删除选项
cache.splice(delete_index, 1);
},
+
+ /**
+ * 向缓存中添加选项
+ * @param {string} id - 选择框元素的ID
+ * @param {HTMLOptionElement} option - 要添加的选项元素
+ */
add_to_cache: function(id, option) {
SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1});
},
+
+ /**
+ * 检查缓存中是否包含指定值的选项
+ * @param {string} id - 选择框元素的ID
+ * @param {string} value - 要检查的选项值
+ * @returns {boolean} 如果包含则返回true,否则返回false
+ */
cache_contains: function(id, value) {
- // Check if an item is contained in the cache
+ // 检查项目是否包含在缓存中
for (const node of SelectBox.cache[id]) {
if (node.value === value) {
return true;
@@ -68,30 +113,53 @@
}
return false;
},
+
+ /**
+ * 将选中的选项从一个选择框移动到另一个选择框
+ * @param {string} from - 源选择框ID
+ * @param {string} to - 目标选择框ID
+ */
move: function(from, to) {
const from_box = document.getElementById(from);
+ // 遍历源选择框中的所有选项
for (const option of from_box.options) {
const option_value = option.value;
+ // 如果选项被选中且在缓存中存在,则移动它
if (option.selected && SelectBox.cache_contains(from, option_value)) {
SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1});
SelectBox.delete_from_cache(from, option_value);
}
}
+ // 重新显示两个选择框
SelectBox.redisplay(from);
SelectBox.redisplay(to);
},
+
+ /**
+ * 将所有选项从一个选择框移动到另一个选择框
+ * @param {string} from - 源选择框ID
+ * @param {string} to - 目标选择框ID
+ */
move_all: function(from, to) {
const from_box = document.getElementById(from);
+ // 遍历源选择框中的所有选项
for (const option of from_box.options) {
const option_value = option.value;
+ // 如果选项在缓存中存在,则移动它
if (SelectBox.cache_contains(from, option_value)) {
SelectBox.add_to_cache(to, {value: option_value, text: option.text, displayed: 1});
SelectBox.delete_from_cache(from, option_value);
}
}
+ // 重新显示两个选择框
SelectBox.redisplay(from);
SelectBox.redisplay(to);
},
+
+ /**
+ * 对选择框中的选项按文本进行排序
+ * @param {string} id - 选择框元素的ID
+ */
sort: function(id) {
SelectBox.cache[id].sort(function(a, b) {
a = a.text.toLowerCase();
@@ -105,12 +173,18 @@
return 0;
} );
},
+
+ /**
+ * 选中选择框中的所有选项
+ * @param {string} id - 选择框元素的ID
+ */
select_all: function(id) {
const box = document.getElementById(id);
+ // 遍历所有选项并选中它们
for (const option of box.options) {
option.selected = true;
}
}
};
window.SelectBox = SelectBox;
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/SelectFilter2.js b/src/collectedstatic/admin/js/SelectFilter2.js
index 970b511..9830951 100644
--- a/src/collectedstatic/admin/js/SelectFilter2.js
+++ b/src/collectedstatic/admin/js/SelectFilter2.js
@@ -1,38 +1,42 @@
/*global SelectBox, gettext, ngettext, interpolate, quickElement, SelectFilter*/
/*
-SelectFilter2 - Turns a multiple-select box into a filter interface.
+SelectFilter2 - 将多选框转换为过滤器界面。
-Requires core.js and SelectBox.js.
+需要 core.js 和 SelectBox.js。
*/
'use strict';
{
window.SelectFilter = {
+ /**
+ * 初始化选择过滤器
+ * @param {string} field_id - 字段ID
+ * @param {string} field_name - 字段名称
+ * @param {boolean} is_stacked - 是否堆叠显示
+ */
init: function(field_id, field_name, is_stacked) {
if (field_id.match(/__prefix__/)) {
- // Don't initialize on empty forms.
+ // 不要在空表单上初始化
return;
}
const from_box = document.getElementById(field_id);
- from_box.id += '_from'; // change its ID
+ from_box.id += '_from'; // 更改ID
from_box.className = 'filtered';
from_box.setAttribute('aria-labelledby', field_id + '_from_title');
+ // 处理from_box的兄弟元素
const selector_chooser = quickElement('ul', selector_div);
selector_chooser.className = 'selector-chooser';
+ // 创建"添加选中"按钮
const add_button = quickElement(
'button',
quickElement('li', selector_chooser),
@@ -87,6 +94,7 @@ Requires core.js and SelectBox.js.
'class', 'selector-add',
'type', 'button'
);
+ // 创建"移除选中"按钮
const remove_button = quickElement(
'button',
quickElement('li', selector_chooser),
@@ -110,6 +118,7 @@ Requires core.js and SelectBox.js.
'class', 'helptext'
);
+ // 创建选中项过滤器
const filter_selected_p = quickElement('p', selector_chosen, '', 'id', field_id + '_filter_selected');
filter_selected_p.className = 'selector-filter';
@@ -126,6 +135,7 @@ Requires core.js and SelectBox.js.
const filter_selected_input = quickElement('input', filter_selected_p, '', 'type', 'text', 'placeholder', gettext("Filter"));
filter_selected_input.id = field_id + '_selected_input';
+ // 创建目标选择框
quickElement(
'select',
selector_chosen,
@@ -137,9 +147,11 @@ Requires core.js and SelectBox.js.
'aria-labelledby', field_id + '_to_title',
'class', 'filtered'
);
+ // 创建警告页脚
const warning_footer = quickElement('div', selector_chosen, '', 'class', 'list-footer-display');
quickElement('span', warning_footer, '', 'id', field_id + '_list-footer-display-text');
quickElement('span', warning_footer, ' ' + gettext('(click to clear)'), 'class', 'list-footer-display__clear');
+ // 创建"全部移除"按钮
const clear_all = quickElement(
'button',
selector_chosen,
@@ -151,7 +163,7 @@ Requires core.js and SelectBox.js.
from_box.name = from_box.name + '_old';
- // Set up the JavaScript event handlers for the select box filter interface
+ // 设置选择框过滤器界面的JavaScript事件处理器
const move_selection = function(e, elem, move_func, from, to) {
if (!elem.hasAttribute('disabled')) {
move_func(from, to);
@@ -161,24 +173,30 @@ Requires core.js and SelectBox.js.
}
e.preventDefault();
};
+ // 监听"全选"按钮点击事件
choose_all.addEventListener('click', function(e) {
move_selection(e, this, SelectBox.move_all, field_id + '_from', field_id + '_to');
});
+ // 监听"添加选中"按钮点击事件
add_button.addEventListener('click', function(e) {
move_selection(e, this, SelectBox.move, field_id + '_from', field_id + '_to');
});
+ // 监听"移除选中"按钮点击事件
remove_button.addEventListener('click', function(e) {
move_selection(e, this, SelectBox.move, field_id + '_to', field_id + '_from');
});
+ // 监听"全部移除"按钮点击事件
clear_all.addEventListener('click', function(e) {
move_selection(e, this, SelectBox.move_all, field_id + '_to', field_id + '_from');
});
+ // 监听警告页脚点击事件
warning_footer.addEventListener('click', function(e) {
filter_selected_input.value = '';
SelectBox.filter(field_id + '_to', '');
SelectFilter.refresh_filtered_warning(field_id);
SelectFilter.refresh_icons(field_id);
});
+ // 监听过滤输入框按键事件
filter_input.addEventListener('keypress', function(e) {
SelectFilter.filter_key_press(e, field_id, '_from', '_to');
});
@@ -188,6 +206,7 @@ Requires core.js and SelectBox.js.
filter_input.addEventListener('keydown', function(e) {
SelectFilter.filter_key_down(e, field_id, '_from', '_to');
});
+ // 监听选中项过滤输入框按键事件
filter_selected_input.addEventListener('keypress', function(e) {
SelectFilter.filter_key_press(e, field_id, '_to', '_from');
});
@@ -197,11 +216,13 @@ Requires core.js and SelectBox.js.
filter_selected_input.addEventListener('keydown', function(e) {
SelectFilter.filter_key_down(e, field_id, '_to', '_from');
});
+ // 监听选择框变更事件
selector_div.addEventListener('change', function(e) {
if (e.target.tagName === 'SELECT') {
SelectFilter.refresh_icons(field_id);
}
});
+ // 监听双击事件
selector_div.addEventListener('dblclick', function(e) {
if (e.target.tagName === 'OPTION') {
if (e.target.closest('select').id === field_id + '_to') {
@@ -212,25 +233,38 @@ Requires core.js and SelectBox.js.
SelectFilter.refresh_icons(field_id);
}
});
+ // 监听表单提交事件
from_box.closest('form').addEventListener('submit', function() {
SelectBox.filter(field_id + '_to', '');
SelectBox.select_all(field_id + '_to');
});
+ // 初始化选择框
SelectBox.init(field_id + '_from');
SelectBox.init(field_id + '_to');
- // Move selected from_box options to to_box
+ // 将选中的from_box选项移动到to_box
SelectBox.move(field_id + '_from', field_id + '_to');
- // Initial icon refresh
+ // 初始刷新图标
SelectFilter.refresh_icons(field_id);
},
+
+ /**
+ * 检查是否有选项被选中
+ * @param {HTMLSelectElement} field - 选择框元素
+ * @returns {boolean} 如果有选项被选中返回true,否则返回false
+ */
any_selected: function(field) {
- // Temporarily add the required attribute and check validity.
+ // 临时添加required属性并检查有效性
field.required = true;
const any_selected = field.checkValidity();
field.required = false;
return any_selected;
},
+
+ /**
+ * 刷新过滤警告信息
+ * @param {string} field_id - 字段ID
+ */
refresh_filtered_warning: function(field_id) {
const count = SelectBox.get_hidden_node_count(field_id + '_to');
const selector = document.getElementById(field_id + '_selector_chosen');
@@ -245,23 +279,41 @@ Requires core.js and SelectBox.js.
selector.className += ' selector-chosen--with-filtered';
}
},
+
+ /**
+ * 刷新过滤选择框
+ * @param {string} field_id - 字段ID
+ */
refresh_filtered_selects: function(field_id) {
SelectBox.filter(field_id + '_from', document.getElementById(field_id + "_input").value);
SelectBox.filter(field_id + '_to', document.getElementById(field_id + "_selected_input").value);
},
+
+ /**
+ * 刷新图标状态
+ * @param {string} field_id - 字段ID
+ */
refresh_icons: function(field_id) {
const from = document.getElementById(field_id + '_from');
const to = document.getElementById(field_id + '_to');
- // Disabled if no items are selected.
+ // 如果没有选项被选中,则禁用按钮
document.getElementById(field_id + '_add').disabled = !SelectFilter.any_selected(from);
document.getElementById(field_id + '_remove').disabled = !SelectFilter.any_selected(to);
- // Disabled if the corresponding box is empty.
+ // 如果对应的选择框为空,则禁用按钮
document.getElementById(field_id + '_add_all').disabled = !from.querySelector('option');
document.getElementById(field_id + '_remove_all').disabled = !to.querySelector('option');
},
+
+ /**
+ * 过滤器按键按下事件处理
+ * @param {KeyboardEvent} event - 键盘事件
+ * @param {string} field_id - 字段ID
+ * @param {string} source - 源选择框后缀
+ * @param {string} target - 目标选择框后缀
+ */
filter_key_press: function(event, field_id, source, target) {
const source_box = document.getElementById(field_id + source);
- // don't submit form if user pressed Enter
+ // 如果用户按下回车键,不要提交表单
if ((event.which && event.which === 13) || (event.keyCode && event.keyCode === 13)) {
source_box.selectedIndex = 0;
SelectBox.move(field_id + source, field_id + target);
@@ -269,6 +321,14 @@ Requires core.js and SelectBox.js.
event.preventDefault();
}
},
+
+ /**
+ * 过滤器按键释放事件处理
+ * @param {KeyboardEvent} event - 键盘事件
+ * @param {string} field_id - 字段ID
+ * @param {string} source - 源选择框后缀
+ * @param {string} filter_input - 过滤输入框后缀
+ */
filter_key_up: function(event, field_id, source, filter_input) {
const input = filter_input || '_input';
const source_box = document.getElementById(field_id + source);
@@ -278,11 +338,19 @@ Requires core.js and SelectBox.js.
SelectFilter.refresh_filtered_warning(field_id);
SelectFilter.refresh_icons(field_id);
},
+
+ /**
+ * 过滤器按键按下事件处理
+ * @param {KeyboardEvent} event - 键盘事件
+ * @param {string} field_id - 字段ID
+ * @param {string} source - 源选择框后缀
+ * @param {string} target - 目标选择框后缀
+ */
filter_key_down: function(event, field_id, source, target) {
const source_box = document.getElementById(field_id + source);
- // right key (39) or left key (37)
+ // 右键(39)或左键(37)
const direction = source === '_from' ? 39 : 37;
- // right arrow -- move across
+ // 右箭头 -- 移动到另一边
if ((event.which && event.which === direction) || (event.keyCode && event.keyCode === direction)) {
const old_index = source_box.selectedIndex;
SelectBox.move(field_id + source, field_id + target);
@@ -291,21 +359,22 @@ Requires core.js and SelectBox.js.
source_box.selectedIndex = (old_index === source_box.length) ? source_box.length - 1 : old_index;
return;
}
- // down arrow -- wrap around
+ // 下箭头 -- 循环选择
if ((event.which && event.which === 40) || (event.keyCode && event.keyCode === 40)) {
source_box.selectedIndex = (source_box.length === source_box.selectedIndex + 1) ? 0 : source_box.selectedIndex + 1;
}
- // up arrow -- wrap around
+ // 上箭头 -- 循环选择
if ((event.which && event.which === 38) || (event.keyCode && event.keyCode === 38)) {
source_box.selectedIndex = (source_box.selectedIndex === 0) ? source_box.length - 1 : source_box.selectedIndex - 1;
}
}
};
+ // 页面加载完成后初始化所有选择过滤器
window.addEventListener('load', function(e) {
document.querySelectorAll('select.selectfilter, select.selectfilterstacked').forEach(function(el) {
const data = el.dataset;
SelectFilter.init(el.id, data.fieldName, parseInt(data.isStacked, 10));
});
});
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/actions.js b/src/collectedstatic/admin/js/actions.js
index 04b25e9..ac42703 100644
--- a/src/collectedstatic/admin/js/actions.js
+++ b/src/collectedstatic/admin/js/actions.js
@@ -1,24 +1,40 @@
/*global gettext, interpolate, ngettext, Actions*/
'use strict';
{
+ /**
+ * 显示指定选择器的元素
+ * @param {string} selector - CSS选择器
+ */
function show(selector) {
document.querySelectorAll(selector).forEach(function(el) {
el.classList.remove('hidden');
});
}
+ /**
+ * 隐藏指定选择器的元素
+ * @param {string} selector - CSS选择器
+ */
function hide(selector) {
document.querySelectorAll(selector).forEach(function(el) {
el.classList.add('hidden');
});
}
+ /**
+ * 显示操作问题提示
+ * @param {Object} options - 配置选项
+ */
function showQuestion(options) {
hide(options.acrossClears);
show(options.acrossQuestions);
hide(options.allContainer);
}
+ /**
+ * 显示清除跨页选择链接
+ * @param {Object} options - 配置选项
+ */
function showClear(options) {
show(options.acrossClears);
hide(options.acrossQuestions);
@@ -27,6 +43,10 @@
hide(options.counterContainer);
}
+ /**
+ * 重置操作状态
+ * @param {Object} options - 配置选项
+ */
function reset(options) {
hide(options.acrossClears);
hide(options.acrossQuestions);
@@ -34,6 +54,10 @@
show(options.counterContainer);
}
+ /**
+ * 清除跨页选择状态
+ * @param {Object} options - 配置选项
+ */
function clearAcross(options) {
reset(options);
const acrossInputs = document.querySelectorAll(options.acrossInput);
@@ -43,6 +67,12 @@
document.querySelector(options.actionContainer).classList.remove(options.selectedClass);
}
+ /**
+ * 选中/取消选中复选框
+ * @param {NodeList} actionCheckboxes - 操作复选框列表
+ * @param {Object} options - 配置选项
+ * @param {boolean} checked - 是否选中
+ */
function checker(actionCheckboxes, options, checked) {
if (checked) {
showQuestion(options);
@@ -55,20 +85,27 @@
});
}
+ /**
+ * 更新选中计数器
+ * @param {NodeList} actionCheckboxes - 操作复选框列表
+ * @param {Object} options - 配置选项
+ */
function updateCounter(actionCheckboxes, options) {
+ // 计算选中的复选框数量
const sel = Array.from(actionCheckboxes).filter(function(el) {
return el.checked;
}).length;
const counter = document.querySelector(options.counterContainer);
- // data-actions-icnt is defined in the generated HTML
- // and contains the total amount of objects in the queryset
+ // data-actions-icnt在生成的HTML中定义,包含查询集中的对象总数
const actions_icnt = Number(counter.dataset.actionsIcnt);
+ // 更新计数器文本
counter.textContent = interpolate(
ngettext('%(sel)s of %(cnt)s selected', '%(sel)s of %(cnt)s selected', sel), {
sel: sel,
cnt: actions_icnt
}, true);
const allToggle = document.getElementById(options.allToggleId);
+ // 如果所有复选框都被选中,则选中全选复选框
allToggle.checked = sel === actionCheckboxes.length;
if (allToggle.checked) {
showQuestion(options);
@@ -77,23 +114,30 @@
}
}
+ // 默认配置选项
const defaults = {
- actionContainer: "div.actions",
- counterContainer: "span.action-counter",
- allContainer: "div.actions span.all",
- acrossInput: "div.actions input.select-across",
- acrossQuestions: "div.actions span.question",
- acrossClears: "div.actions span.clear",
- allToggleId: "action-toggle",
- selectedClass: "selected"
+ actionContainer: "div.actions", // 操作容器
+ counterContainer: "span.action-counter", // 计数器容器
+ allContainer: "div.actions span.all", // 全选容器
+ acrossInput: "div.actions input.select-across", // 跨页选择输入框
+ acrossQuestions: "div.actions span.question", // 跨页选择问题
+ acrossClears: "div.actions span.clear", // 跨页选择清除
+ allToggleId: "action-toggle", // 全选切换ID
+ selectedClass: "selected" // 选中项的CSS类
};
+ /**
+ * 初始化操作功能
+ * @param {NodeList} actionCheckboxes - 操作复选框列表
+ * @param {Object} options - 配置选项
+ */
window.Actions = function(actionCheckboxes, options) {
options = Object.assign({}, defaults, options);
- let list_editable_changed = false;
- let lastChecked = null;
- let shiftPressed = false;
+ let list_editable_changed = false; // 可编辑列表是否已更改
+ let lastChecked = null; // 最后选中的复选框
+ let shiftPressed = false; // Shift键是否按下
+ // 监听键盘事件,记录Shift键状态
document.addEventListener('keydown', (event) => {
shiftPressed = event.shiftKey;
});
@@ -102,11 +146,13 @@
shiftPressed = event.shiftKey;
});
+ // 监听全选复选框点击事件
document.getElementById(options.allToggleId).addEventListener('click', function(event) {
checker(actionCheckboxes, options, this.checked);
updateCounter(actionCheckboxes, options);
});
+ // 监听跨页选择问题链接点击事件
document.querySelectorAll(options.acrossQuestions + " a").forEach(function(el) {
el.addEventListener('click', function(event) {
event.preventDefault();
@@ -118,6 +164,7 @@
});
});
+ // 监听跨页选择清除链接点击事件
document.querySelectorAll(options.acrossClears + " a").forEach(function(el) {
el.addEventListener('click', function(event) {
event.preventDefault();
@@ -128,6 +175,12 @@
});
});
+ /**
+ * 获取受Shift键影响的复选框
+ * @param {HTMLInputElement} target - 目标复选框
+ * @param {boolean} withModifier - 是否按下修饰键
+ * @returns {Array} 受影响的复选框数组
+ */
function affectedCheckboxes(target, withModifier) {
const multiSelect = (lastChecked && withModifier && lastChecked !== target);
if (!multiSelect) {
@@ -142,6 +195,7 @@
return filtered;
};
+ // 监听结果列表中的变更事件
Array.from(document.getElementById('result_list').tBodies).forEach(function(el) {
el.addEventListener('change', function(event) {
const target = event.target;
@@ -156,8 +210,10 @@
});
});
+ // 监听索引按钮点击事件
document.querySelector('#changelist-form button[name=index]').addEventListener('click', function(event) {
if (list_editable_changed) {
+ // 如果有未保存的更改,提示用户确认
const confirmed = confirm(gettext("You have unsaved changes on individual editable fields. If you run an action, your unsaved changes will be lost."));
if (!confirmed) {
event.preventDefault();
@@ -166,10 +222,11 @@
});
const el = document.querySelector('#changelist-form input[name=_save]');
- // The button does not exist if no fields are editable.
+ // 如果存在保存按钮(当有可编辑字段时存在)
if (el) {
el.addEventListener('click', function(event) {
if (document.querySelector('[name=action]').value) {
+ // 根据是否有未保存的更改显示不同的提示信息
const text = list_editable_changed
? gettext("You have selected an action, but you haven’t saved your changes to individual fields yet. Please click OK to save. You’ll need to re-run the action.")
: gettext("You have selected an action, and you haven’t made any changes on individual fields. You’re probably looking for the Go button rather than the Save button.");
@@ -179,13 +236,11 @@
}
});
}
- // Sync counter when navigating to the page, such as through the back
- // button.
+ // 页面显示时同步计数器,例如通过后退按钮导航到页面时
window.addEventListener('pageshow', (event) => updateCounter(actionCheckboxes, options));
};
- // Call function fn when the DOM is loaded and ready. If it is already
- // loaded, call the function now.
+ // 页面加载完成后调用指定函数。如果页面已经加载完成,则立即调用该函数
// http://youmightnotneedjquery.com/#ready
function ready(fn) {
if (document.readyState !== 'loading') {
@@ -195,10 +250,11 @@
}
}
+ // 页面加载完成后初始化操作功能
ready(function() {
const actionsEls = document.querySelectorAll('tr input.action-select');
if (actionsEls.length > 0) {
Actions(actionsEls);
}
});
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/admin/DateTimeShortcuts.js b/src/collectedstatic/admin/js/admin/DateTimeShortcuts.js
index aa1cae9..2837b4d 100644
--- a/src/collectedstatic/admin/js/admin/DateTimeShortcuts.js
+++ b/src/collectedstatic/admin/js/admin/DateTimeShortcuts.js
@@ -1,51 +1,60 @@
/*global Calendar, findPosX, findPosY, get_format, gettext, gettext_noop, interpolate, ngettext, quickElement*/
-// Inserts shortcut buttons after all of the following:
+// 在以下元素后插入快捷按钮:
//
//
'use strict';
{
const DateTimeShortcuts = {
- calendars: [],
- calendarInputs: [],
- clockInputs: [],
- clockHours: {
+ calendars: [], // 日历数组
+ calendarInputs: [], // 日历输入框数组
+ clockInputs: [], // 时钟输入框数组
+ clockHours: { // 时钟快捷时间选项
default_: [
- [gettext_noop('Now'), -1],
- [gettext_noop('Midnight'), 0],
- [gettext_noop('6 a.m.'), 6],
- [gettext_noop('Noon'), 12],
- [gettext_noop('6 p.m.'), 18]
+ [gettext_noop('Now'), -1], // 现在
+ [gettext_noop('Midnight'), 0], // 午夜
+ [gettext_noop('6 a.m.'), 6], // 早上6点
+ [gettext_noop('Noon'), 12], // 中午
+ [gettext_noop('6 p.m.'), 18] // 晚上6点
]
},
- dismissClockFunc: [],
- dismissCalendarFunc: [],
- calendarDivName1: 'calendarbox', // name of calendar
Choose a time
+ // 选择时间
//
- //
+ //
//
@@ -272,9 +295,9 @@
//
//
");
addButton = $parent.find("tr:last a");
} else {
- // Otherwise, insert it immediately after the last form:
+ // 否则,将其插入到最后一个表单之后:
$this.filter(":last").after('");
addButton = $this.filter(":last").next().find("a");
}
}
+ // 为添加按钮绑定点击事件处理器
addButton.on('click', addInlineClickHandler);
};
+ /**
+ * 内联添加按钮点击事件处理器
+ * @param {Event} e - 点击事件
+ */
const addInlineClickHandler = function(e) {
e.preventDefault();
const template = $("#" + options.prefix + "-empty");
const row = template.clone(true);
+ // 移除空行CSS类,添加表单CSS类,设置ID
row.removeClass(options.emptyCssClass)
.addClass(options.formCssClass)
.attr("id", options.prefix + "-" + nextIndex);
addInlineDeleteButton(row);
+ // 更新新表单中所有元素的索引
row.find("*").each(function() {
updateElementIndex(this, options.prefix, totalForms.val());
});
- // Insert the new form when it has been fully edited.
+ // 在完全编辑后插入新表单
row.insertBefore($(template));
- // Update number of total forms.
+ // 更新总表单数
$(totalForms).val(parseInt(totalForms.val(), 10) + 1);
nextIndex += 1;
- // Hide the add button if there's a limit and it's been reached.
+ // 如果达到限制数量,隐藏添加按钮
if ((maxForms.val() !== '') && (maxForms.val() - totalForms.val()) <= 0) {
addButton.parent().hide();
}
- // Show the remove buttons if there are more than min_num.
+ // 如果表单数超过最小数量,显示删除按钮
toggleDeleteButtonVisibility(row.closest('.inline-group'));
- // Pass the new form to the post-add callback, if provided.
+ // 如果提供了添加后的回调函数,则调用它
if (options.added) {
options.added(row);
}
+ // 触发formset:added自定义事件
row.get(0).dispatchEvent(new CustomEvent("formset:added", {
bubbles: true,
detail: {
@@ -97,60 +118,61 @@
};
/**
- * The "X" button that is part of every unsaved inline.
- * (When saved, it is replaced with a "Delete" checkbox.)
+ * 为每个未保存的内联表单添加"X"按钮
+ * (保存后会被"删除"复选框替换)
+ * @param {jQuery} row - 表单行
*/
const addInlineDeleteButton = function(row) {
if (row.is("tr")) {
- // If the forms are laid out in table rows, insert
- // the remove button into the last table cell:
+ // 如果表单以表格行形式排列,将删除按钮插入到最后一个单元格:
row.children(":last").append('");
} else if (row.is("ul") || row.is("ol")) {
- // If they're laid out as an ordered/unordered list,
- // insert an ' + options.addText + "
+ // 显示或隐藏父级 元素
o.node.parentNode.parentNode.style.display = displayValue;
}
+ // 根据是否有匹配项设置输入框的样式
if (!filterValue || matches) {
event.target.classList.remove('no-results');
} else {
event.target.classList.add('no-results');
}
+ // 将过滤值保存到sessionStorage中
sessionStorage.setItem('django.admin.navSidebarFilterValue', filterValue);
}
+ // 获取导航过滤输入框并添加事件监听器
const nav = document.getElementById('nav-filter');
- nav.addEventListener('change', checkValue, false);
- nav.addEventListener('input', checkValue, false);
- nav.addEventListener('keyup', checkValue, false);
+ nav.addEventListener('change', checkValue, false); // 变更事件
+ nav.addEventListener('input', checkValue, false); // 输入事件
+ nav.addEventListener('keyup', checkValue, false); // 键盘弹起事件
+ // 从sessionStorage获取之前保存的过滤值并应用
const storedValue = sessionStorage.getItem('django.admin.navSidebarFilterValue');
if (storedValue) {
nav.value = storedValue;
@@ -76,4 +103,4 @@
}
window.initSidebarQuickFilter = initSidebarQuickFilter;
initSidebarQuickFilter();
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/popup_response.js b/src/collectedstatic/admin/js/popup_response.js
index fecf0f4..86e1e3e 100644
--- a/src/collectedstatic/admin/js/popup_response.js
+++ b/src/collectedstatic/admin/js/popup_response.js
@@ -1,15 +1,21 @@
'use strict';
{
+ // 从页面中获取弹窗响应的初始化数据
const initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse);
+
+ // 根据不同的操作类型执行相应的处理函数
switch(initData.action) {
case 'change':
+ // 处理修改对象的弹窗响应
opener.dismissChangeRelatedObjectPopup(window, initData.value, initData.obj, initData.new_value);
break;
case 'delete':
+ // 处理删除对象的弹窗响应
opener.dismissDeleteRelatedObjectPopup(window, initData.value);
break;
default:
+ // 默认处理添加对象的弹窗响应
opener.dismissAddRelatedObjectPopup(window, initData.value, initData.obj);
break;
}
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/prepopulate.js b/src/collectedstatic/admin/js/prepopulate.js
index 89e95ab..440d683 100644
--- a/src/collectedstatic/admin/js/prepopulate.js
+++ b/src/collectedstatic/admin/js/prepopulate.js
@@ -2,42 +2,57 @@
'use strict';
{
const $ = django.jQuery;
+ /**
+ * 预填充插件
+ * 根据依赖字段的值填充选定字段,生成URL友好的字符串
+ * @param {Array} dependencies - 依赖字段ID数组
+ * @param {number} maxLength - URLify字符串的最大长度
+ * @param {boolean} allowUnicode - URLify字符串是否支持Unicode
+ * @returns {jQuery} jQuery对象
+ */
$.fn.prepopulate = function(dependencies, maxLength, allowUnicode) {
/*
- Depends on urlify.js
- Populates a selected field with the values of the dependent fields,
- URLifies and shortens the string.
- dependencies - array of dependent fields ids
- maxLength - maximum length of the URLify'd string
- allowUnicode - Unicode support of the URLify'd string
+ 依赖 urlify.js
+ 使用依赖字段的值填充选定字段,生成URL友好的并截短的字符串。
+ dependencies - 依赖字段ID数组
+ maxLength - URLify处理后字符串的最大长度
+ allowUnicode - URLify处理后的字符串是否支持Unicode
*/
return this.each(function() {
const prepopulatedField = $(this);
+ /**
+ * 填充字段值
+ */
const populate = function() {
- // Bail if the field's value has been changed by the user
+ // 如果用户已更改字段值,则不进行预填充
if (prepopulatedField.data('_changed')) {
return;
}
const values = [];
+ // 收集所有依赖字段的值
$.each(dependencies, function(i, field) {
field = $(field);
if (field.val().length > 0) {
values.push(field.val());
}
});
+ // 使用URLify函数处理连接后的值,并设置到预填充字段中
prepopulatedField.val(URLify(values.join(' '), maxLength, allowUnicode));
};
+ // 初始化字段变更标记为false
prepopulatedField.data('_changed', false);
+ // 监听字段变更事件,标记字段已被用户更改
prepopulatedField.on('change', function() {
prepopulatedField.data('_changed', true);
});
+ // 如果预填充字段为空,则监听依赖字段的事件并进行填充
if (!prepopulatedField.val()) {
$(dependencies.join(',')).on('keyup change focus', populate);
}
});
};
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/prepopulate_init.js b/src/collectedstatic/admin/js/prepopulate_init.js
index a58841f..bdf00c3 100644
--- a/src/collectedstatic/admin/js/prepopulate_init.js
+++ b/src/collectedstatic/admin/js/prepopulate_init.js
@@ -1,15 +1,21 @@
'use strict';
{
const $ = django.jQuery;
+ // 从页面常量中获取预填充字段的配置信息
const fields = $('#django-admin-prepopulated-fields-constants').data('prepopulatedFields');
+
+ // 遍历所有预填充字段并进行初始化
$.each(fields, function(index, field) {
+ // 为所有空表单中的预填充字段添加CSS类
$(
'.empty-form .form-row .field-' + field.name +
', .empty-form.form-row .field-' + field.name +
', .empty-form .form-row.field-' + field.name
).addClass('prepopulated_field');
+
+ // 为字段元素设置依赖列表数据,并调用prepopulate插件进行初始化
$(field.id).data('dependency_list', field.dependency_list).prepopulate(
field.dependency_ids, field.maxLength, field.allowUnicode
);
});
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/theme.js b/src/collectedstatic/admin/js/theme.js
index e79d375..cf2d5dc 100644
--- a/src/collectedstatic/admin/js/theme.js
+++ b/src/collectedstatic/admin/js/theme.js
@@ -1,20 +1,32 @@
'use strict';
{
+ /**
+ * 设置主题模式
+ * @param {string} mode - 主题模式,可选值: "light"(浅色), "dark"(深色), "auto"(自动)
+ */
function setTheme(mode) {
+ // 验证主题模式参数是否有效
if (mode !== "light" && mode !== "dark" && mode !== "auto") {
console.error(`Got invalid theme mode: ${mode}. Resetting to auto.`);
mode = "auto";
}
+ // 设置文档根元素的主题属性
document.documentElement.dataset.theme = mode;
+ // 将主题选择保存到本地存储
localStorage.setItem("theme", mode);
}
+ /**
+ * 循环切换主题模式
+ */
function cycleTheme() {
+ // 获取当前主题设置,默认为"auto"
const currentTheme = localStorage.getItem("theme") || "auto";
+ // 检查用户是否偏好深色主题
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
if (prefersDark) {
- // Auto (dark) -> Light -> Dark
+ // 深色偏好下的主题切换顺序: 自动(深色) -> 浅色 -> 深色
if (currentTheme === "auto") {
setTheme("light");
} else if (currentTheme === "light") {
@@ -23,7 +35,7 @@
setTheme("auto");
}
} else {
- // Auto (light) -> Dark -> Light
+ // 浅色偏好下的主题切换顺序: 自动(浅色) -> 深色 -> 浅色
if (currentTheme === "auto") {
setTheme("dark");
} else if (currentTheme === "dark") {
@@ -34,12 +46,16 @@
}
}
+ /**
+ * 初始化主题设置
+ */
function initTheme() {
- // set theme defined in localStorage if there is one, or fallback to auto mode
+ // 如果本地存储中有主题设置则使用,否则默认使用自动模式
const currentTheme = localStorage.getItem("theme");
currentTheme ? setTheme(currentTheme) : setTheme("auto");
}
+ // 页面加载完成后为所有主题切换按钮添加点击事件监听器
window.addEventListener('load', function(_) {
const buttons = document.getElementsByClassName("theme-toggle");
Array.from(buttons).forEach((btn) => {
@@ -47,5 +63,6 @@
});
});
+ // 初始化主题
initTheme();
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/unusable_password_field.js b/src/collectedstatic/admin/js/unusable_password_field.js
index ec26238..7ce6004 100644
--- a/src/collectedstatic/admin/js/unusable_password_field.js
+++ b/src/collectedstatic/admin/js/unusable_password_field.js
@@ -1,29 +1,39 @@
"use strict";
-// Fallback JS for browsers which do not support :has selector used in
-// admin/css/unusable_password_fields.css
-// Remove file once all supported browsers support :has selector
+// 为不支持:has选择器的浏览器提供的后备JS方案
+// 用于admin/css/unusable_password_fields.css
+// 一旦所有支持的浏览器都支持:has选择器,可以删除此文件
try {
- // If browser does not support :has selector this will raise an error
+ // 如果浏览器不支持:has选择器,这将引发错误
document.querySelector("form:has(input)");
} catch (error) {
- console.log("Defaulting to javascript for usable password form management: " + error);
- // JS replacement for unsupported :has selector
+ console.log("默认使用JavaScript管理可用密码表单: " + error);
+ // 不支持:has选择器时的JS替代方案
document.querySelectorAll('input[name="usable_password"]').forEach(option => {
+ // 为每个选项添加变更事件监听器
option.addEventListener('change', function() {
+ // 判断是否为可用密码
const usablePassword = (this.value === "true" ? this.checked : !this.checked);
+ // 获取提交按钮和警告信息元素
const submit1 = document.querySelector('input[type="submit"].set-password');
const submit2 = document.querySelector('input[type="submit"].unset-password');
const messages = document.querySelector('#id_unusable_warning');
+
+ // 根据密码可用性显示或隐藏密码输入字段
document.getElementById('id_password1').closest('.form-row').hidden = !usablePassword;
document.getElementById('id_password2').closest('.form-row').hidden = !usablePassword;
+
+ // 根据密码可用性显示或隐藏警告信息
if (messages) {
messages.hidden = usablePassword;
}
+
+ // 根据密码可用性显示或隐藏相应的提交按钮
if (submit1 && submit2) {
submit1.hidden = !usablePassword;
submit2.hidden = usablePassword;
}
});
+ // 触发初始变更事件
option.dispatchEvent(new Event('change'));
});
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/urlify.js b/src/collectedstatic/admin/js/urlify.js
index 9fc0409..d52111f 100644
--- a/src/collectedstatic/admin/js/urlify.js
+++ b/src/collectedstatic/admin/js/urlify.js
@@ -1,6 +1,7 @@
/*global XRegExp*/
'use strict';
{
+ // 拉丁字符映射表
const LATIN_MAP = {
'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE',
'Ç': 'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I',
@@ -13,9 +14,13 @@
'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u',
'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
};
+
+ // 拉丁符号映射表
const LATIN_SYMBOLS_MAP = {
'©': '(c)'
};
+
+ // 希腊字符映射表
const GREEK_MAP = {
'α': 'a', 'β': 'b', 'γ': 'g', 'δ': 'd', 'ε': 'e', 'ζ': 'z', 'η': 'h',
'θ': '8', 'ι': 'i', 'κ': 'k', 'λ': 'l', 'μ': 'm', 'ν': 'n', 'ξ': '3',
@@ -28,14 +33,20 @@
'Φ': 'F', 'Χ': 'X', 'Ψ': 'PS', 'Ω': 'W', 'Ά': 'A', 'Έ': 'E', 'Ί': 'I',
'Ό': 'O', 'Ύ': 'Y', 'Ή': 'H', 'Ώ': 'W', 'Ϊ': 'I', 'Ϋ': 'Y'
};
+
+ // 土耳其字符映射表
const TURKISH_MAP = {
'ş': 's', 'Ş': 'S', 'ı': 'i', 'İ': 'I', 'ç': 'c', 'Ç': 'C', 'ü': 'u',
'Ü': 'U', 'ö': 'o', 'Ö': 'O', 'ğ': 'g', 'Ğ': 'G'
};
+
+ // 罗马尼亚字符映射表
const ROMANIAN_MAP = {
'ă': 'a', 'î': 'i', 'ș': 's', 'ț': 't', 'â': 'a',
'Ă': 'A', 'Î': 'I', 'Ș': 'S', 'Ț': 'T', 'Â': 'A'
};
+
+ // 俄语字符映射表
const RUSSIAN_MAP = {
'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo',
'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'j', 'к': 'k', 'л': 'l', 'м': 'm',
@@ -48,15 +59,21 @@
'Ф': 'F', 'Х': 'H', 'Ц': 'C', 'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Sh', 'Ъ': '',
'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu', 'Я': 'Ya'
};
+
+ // 乌克兰字符映射表
const UKRAINIAN_MAP = {
'Є': 'Ye', 'І': 'I', 'Ї': 'Yi', 'Ґ': 'G', 'є': 'ye', 'і': 'i',
'ї': 'yi', 'ґ': 'g'
};
+
+ // 捷克字符映射表
const CZECH_MAP = {
'č': 'c', 'ď': 'd', 'ě': 'e', 'ň': 'n', 'ř': 'r', 'š': 's', 'ť': 't',
'ů': 'u', 'ž': 'z', 'Č': 'C', 'Ď': 'D', 'Ě': 'E', 'Ň': 'N', 'Ř': 'R',
'Š': 'S', 'Ť': 'T', 'Ů': 'U', 'Ž': 'Z'
};
+
+ // 斯洛伐克字符映射表
const SLOVAK_MAP = {
'á': 'a', 'ä': 'a', 'č': 'c', 'ď': 'd', 'é': 'e', 'í': 'i', 'ľ': 'l',
'ĺ': 'l', 'ň': 'n', 'ó': 'o', 'ô': 'o', 'ŕ': 'r', 'š': 's', 'ť': 't',
@@ -65,39 +82,53 @@
'Ĺ': 'L', 'Ň': 'N', 'Ó': 'O', 'Ô': 'O', 'Ŕ': 'R', 'Š': 'S', 'Ť': 'T',
'Ú': 'U', 'Ý': 'Y', 'Ž': 'Z'
};
+
+ // 波兰字符映射表
const POLISH_MAP = {
'ą': 'a', 'ć': 'c', 'ę': 'e', 'ł': 'l', 'ń': 'n', 'ó': 'o', 'ś': 's',
'ź': 'z', 'ż': 'z',
'Ą': 'A', 'Ć': 'C', 'Ę': 'E', 'Ł': 'L', 'Ń': 'N', 'Ó': 'O', 'Ś': 'S',
'Ź': 'Z', 'Ż': 'Z'
};
+
+ // 拉脱维亚字符映射表
const LATVIAN_MAP = {
'ā': 'a', 'č': 'c', 'ē': 'e', 'ģ': 'g', 'ī': 'i', 'ķ': 'k', 'ļ': 'l',
'ņ': 'n', 'š': 's', 'ū': 'u', 'ž': 'z',
'Ā': 'A', 'Č': 'C', 'Ē': 'E', 'Ģ': 'G', 'Ī': 'I', 'Ķ': 'K', 'Ļ': 'L',
'Ņ': 'N', 'Š': 'S', 'Ū': 'U', 'Ž': 'Z'
};
+
+ // 阿拉伯字符映射表
const ARABIC_MAP = {
'أ': 'a', 'ب': 'b', 'ت': 't', 'ث': 'th', 'ج': 'g', 'ح': 'h', 'خ': 'kh', 'د': 'd',
'ذ': 'th', 'ر': 'r', 'ز': 'z', 'س': 's', 'ش': 'sh', 'ص': 's', 'ض': 'd', 'ط': 't',
'ظ': 'th', 'ع': 'aa', 'غ': 'gh', 'ف': 'f', 'ق': 'k', 'ك': 'k', 'ل': 'l', 'م': 'm',
'ن': 'n', 'ه': 'h', 'و': 'o', 'ي': 'y'
};
+
+ // 立陶宛字符映射表
const LITHUANIAN_MAP = {
'ą': 'a', 'č': 'c', 'ę': 'e', 'ė': 'e', 'į': 'i', 'š': 's', 'ų': 'u',
'ū': 'u', 'ž': 'z',
'Ą': 'A', 'Č': 'C', 'Ę': 'E', 'Ė': 'E', 'Į': 'I', 'Š': 'S', 'Ų': 'U',
'Ū': 'U', 'Ž': 'Z'
};
+
+ // 塞尔维亚字符映射表
const SERBIAN_MAP = {
'ђ': 'dj', 'ј': 'j', 'љ': 'lj', 'њ': 'nj', 'ћ': 'c', 'џ': 'dz',
'đ': 'dj', 'Ђ': 'Dj', 'Ј': 'j', 'Љ': 'Lj', 'Њ': 'Nj', 'Ћ': 'C',
'Џ': 'Dz', 'Đ': 'Dj'
};
+
+ // 阿塞拜疆字符映射表
const AZERBAIJANI_MAP = {
'ç': 'c', 'ə': 'e', 'ğ': 'g', 'ı': 'i', 'ö': 'o', 'ş': 's', 'ü': 'u',
'Ç': 'C', 'Ə': 'E', 'Ğ': 'G', 'İ': 'I', 'Ö': 'O', 'Ş': 'S', 'Ü': 'U'
};
+
+ // 格鲁吉亚字符映射表
const GEORGIAN_MAP = {
'ა': 'a', 'ბ': 'b', 'გ': 'g', 'დ': 'd', 'ე': 'e', 'ვ': 'v', 'ზ': 'z',
'თ': 't', 'ი': 'i', 'კ': 'k', 'ლ': 'l', 'მ': 'm', 'ნ': 'n', 'ო': 'o',
@@ -106,6 +137,7 @@
'წ': 'w', 'ჭ': 'ch', 'ხ': 'x', 'ჯ': 'j', 'ჰ': 'h'
};
+ // 所有字符映射表的数组
const ALL_DOWNCODE_MAPS = [
LATIN_MAP,
LATIN_SYMBOLS_MAP,
@@ -125,19 +157,30 @@
GEORGIAN_MAP
];
+ // 字符降码处理对象
const Downcoder = {
+ /**
+ * 初始化字符映射表
+ */
'Initialize': function() {
- if (Downcoder.map) { // already made
+ if (Downcoder.map) { // 如果已经初始化过,则直接返回
return;
}
Downcoder.map = {};
+ // 将所有映射表合并到一个对象中
for (const lookup of ALL_DOWNCODE_MAPS) {
Object.assign(Downcoder.map, lookup);
}
+ // 创建用于匹配所有映射字符的正则表达式
Downcoder.regex = new RegExp(Object.keys(Downcoder.map).join('|'), 'g');
}
};
+ /**
+ * 将特殊字符转换为普通字符
+ * @param {string} slug - 需要转换的字符串
+ * @returns {string} 转换后的字符串
+ */
function downcode(slug) {
Downcoder.Initialize();
return slug.replace(Downcoder.regex, function(m) {
@@ -146,24 +189,31 @@
}
+ /**
+ * 将字符串转换为URL友好的格式
+ * 例如将"Petty theft"转换为"petty-theft"
+ * @param {string} s - 输入字符串
+ * @param {number} num_chars - 最大字符数
+ * @param {boolean} allowUnicode - 是否允许Unicode字符
+ * @returns {string} URL友好的字符串
+ */
function URLify(s, num_chars, allowUnicode) {
- // changes, e.g., "Petty theft" to "petty-theft"
+ // 如果不允许Unicode字符,则进行字符降码处理
if (!allowUnicode) {
s = downcode(s);
}
- s = s.toLowerCase(); // convert to lowercase
- // if downcode doesn't hit, the char will be stripped here
+ s = s.toLowerCase(); // 转换为小写
+ // 如果降码处理没有命中,字符将在这里被移除
if (allowUnicode) {
- // Keep Unicode letters including both lowercase and uppercase
- // characters, whitespace, and dash; remove other characters.
+ // 保留Unicode字母,包括大小写字符、空白字符和连字符;移除其他字符
s = XRegExp.replace(s, XRegExp('[^-_\\p{L}\\p{N}\\s]', 'g'), '');
} else {
- s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars
+ s = s.replace(/[^-\w\s]/g, ''); // 移除不需要的字符
}
- s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
- s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens
- s = s.substring(0, num_chars); // trim to first num_chars chars
- return s.replace(/-+$/g, ''); // trim any trailing hyphens
+ s = s.replace(/^\s+|\s+$/g, ''); // 去除开头和结尾的空格
+ s = s.replace(/[-\s]+/g, '-'); // 将空格转换为连字符
+ s = s.substring(0, num_chars); // 截取指定长度的字符
+ return s.replace(/-+$/g, ''); // 去除末尾的连字符
}
window.URLify = URLify;
-}
+}
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/vendor/select2/i18n/zh-CN.js b/src/collectedstatic/admin/js/vendor/select2/i18n/zh-CN.js
index 2c5649d..d2eea2a 100644
--- a/src/collectedstatic/admin/js/vendor/select2/i18n/zh-CN.js
+++ b/src/collectedstatic/admin/js/vendor/select2/i18n/zh-CN.js
@@ -1,3 +1,22 @@
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
+// 简体中文国际化语言包
+// 为Select2下拉选择框提供简体中文的用户界面文本翻译
-!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(n){return"请删除"+(n.input.length-n.maximum)+"个字符"},inputTooShort:function(n){return"请再输入至少"+(n.minimum-n.input.length)+"个字符"},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(n){return"最多只能选择"+n.maximum+"个项目"},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"},removeAllItems:function(){return"删除所有项目"}}}),n.define,n.require}();
\ No newline at end of file
+!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-CN",[],function(){return{
+ // 加载结果失败时的错误提示
+ errorLoading:function(){return"无法载入结果。"},
+ // 输入内容过长时的提示信息
+ inputTooLong:function(n){return"请删除"+(n.input.length-n.maximum)+"个字符"},
+ // 输入内容过短时的提示信息
+ inputTooShort:function(n){return"请再输入至少"+(n.minimum-n.input.length)+"个字符"},
+ // 加载更多结果时的提示信息
+ loadingMore:function(){return"载入更多结果…"},
+ // 超过最大选择数量时的提示信息
+ maximumSelected:function(n){return"最多只能选择"+n.maximum+"个项目"},
+ // 没有找到匹配结果时的提示信息
+ noResults:function(){return"未找到结果"},
+ // 搜索过程中的提示信息
+ searching:function(){return"搜索中…"},
+ // 删除所有选中项的提示信息
+ removeAllItems:function(){return"删除所有项目"}
+}}),n.define,n.require}();
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/vendor/select2/i18n/zh-TW.js b/src/collectedstatic/admin/js/vendor/select2/i18n/zh-TW.js
index 570a566..5ae25fe 100644
--- a/src/collectedstatic/admin/js/vendor/select2/i18n/zh-TW.js
+++ b/src/collectedstatic/admin/js/vendor/select2/i18n/zh-TW.js
@@ -1,3 +1,20 @@
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
+// 繁体中文国际化语言包
+// 为Select2下拉选择框提供繁体中文的用户界面文本翻译
-!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-TW",[],function(){return{inputTooLong:function(n){return"請刪掉"+(n.input.length-n.maximum)+"個字元"},inputTooShort:function(n){return"請再輸入"+(n.minimum-n.input.length)+"個字元"},loadingMore:function(){return"載入中…"},maximumSelected:function(n){return"你只能選擇最多"+n.maximum+"項"},noResults:function(){return"沒有找到相符的項目"},searching:function(){return"搜尋中…"},removeAllItems:function(){return"刪除所有項目"}}}),n.define,n.require}();
\ No newline at end of file
+!function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-TW",[],function(){return{
+ // 输入内容过长时的提示信息
+ inputTooLong:function(n){return"請刪掉"+(n.input.length-n.maximum)+"個字元"},
+ // 输入内容过短时的提示信息
+ inputTooShort:function(n){return"請再輸入"+(n.minimum-n.input.length)+"個字元"},
+ // 加载更多结果时的提示信息
+ loadingMore:function(){return"載入中…"},
+ // 超过最大选择数量时的提示信息
+ maximumSelected:function(n){return"你只能選擇最多"+n.maximum+"項"},
+ // 没有找到匹配结果时的提示信息
+ noResults:function(){return"沒有找到相符的項目"},
+ // 搜索过程中的提示信息
+ searching:function(){return"搜尋中…"},
+ // 删除所有选中项的提示信息
+ removeAllItems:function(){return"刪除所有項目"}
+}}),n.define,n.require}();
\ No newline at end of file
diff --git a/src/collectedstatic/admin/js/vendor/select2/select2.full.js b/src/collectedstatic/admin/js/vendor/select2/select2.full.js
index 358572a..876d5b7 100644
--- a/src/collectedstatic/admin/js/vendor/select2/select2.full.js
+++ b/src/collectedstatic/admin/js/vendor/select2/select2.full.js
@@ -5,18 +5,104 @@
* Released under the MIT license
* https://github.com/select2/select2/blob/master/LICENSE.md
*/
+// Select2是一个基于jQuery的下拉选择框增强插件,提供了更强大的功能和更好的用户体验
+// 此文件是Select2的完整版本,包含了所有功能实现
+
+// almond.js - 一个轻量级的AMD模块加载器实现
+// 用于在没有完整AMD加载器(如RequireJS)的环境中运行Select2
+var S2 =(function () {
+ // 恢复Select2 AMD加载器,使其可以被使用
+ // 主要用于语言文件中,因为在那些文件中加载器可能不存在
+ if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
+ var S2 = jQuery.fn.select2.amd;
+ }
+ var define, requirejs, require, requirejsLib;
+
+ if (typeof S2 === 'undefined') {
+ S2 = {};
+ }
+
+ define = S2.define = function (id, deps, factory) {
+ if (typeof id !== 'string') {
+ throw new Error('Module id must be a string');
+ }
+
+ if (deps.indexOf('exports') === -1) {
+ throw new Error('Module ' + id + ' must have an exports dependency');
+ }
+
+ if (deps.indexOf('module') === -1) {
+ throw new Error('Module ' + id + ' must have a module dependency');
+ }
+
+ if (S2.registry[id]) {
+ throw new Error('Module ' + id + ' is already defined');
+ }
+
+ S2.registry[id] = {
+ id: id,
+ deps: deps,
+ factory: factory
+ };
+ };
+
+ requirejs = S2.requirejs = S2.require = require = function (deps, callback) {
+ var module, dep, depModule, exports, callbackType,
+ modules = [],
+ i, j, len, args = [], arg;
+
+ for (i = 0, len = deps.length; i < len; i++) {
+ dep = deps[i];
+ if (dep === 'exports') {
+ exports = {};
+ args.push(exports);
+ } else if (dep === 'module') {
+ module = {
+ id: id,
+ uri: '',
+ exports: exports
+ };
+ args.push(module);
+ } else {
+ depModule = S2.registry[dep];
+ if (!depModule) {
+ throw new Error('Module ' + dep + ' is not defined');
+ }
+ modules.push(depModule);
+ args.push(depModule.exports);
+ }
+ }
+
+ callbackType = typeof callback;
+
+ if (callbackType === 'function') {
+ callback.apply(null, args);
+ } else if (callbackType === 'string') {
+ return eval(callback);
+ }
+
+ return exports;
+ };
+
+ define.amd = {
+ jQuery: true
+ };
+
+ S2.registry = {};
+
+ return S2;
+})();
+
;(function (factory) {
+ // 检测模块加载器类型并进行相应处理
if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
+ // AMD模块加载器支持
define(['jquery'], factory);
} else if (typeof module === 'object' && module.exports) {
- // Node/CommonJS
+ // Node/CommonJS模块支持
module.exports = function (root, jQuery) {
if (jQuery === undefined) {
- // require('jQuery') returns a factory that requires window to
- // build a jQuery instance, we normalize how we use modules
- // that require this pattern but the window provided is a noop
- // if it's defined (how jquery works)
+ // 如果jQuery未定义,则尝试通过require加载
if (typeof window !== 'undefined') {
jQuery = require('jquery');
}
@@ -28,10 +114,12 @@
return jQuery;
};
} else {
- // Browser globals
+ // 浏览器全局变量支持
factory(jQuery);
}
} (function (jQuery) {
+ // 这里是Select2的主要实现代码
+
// This is needed so we can catch the AMD loader configuration and use it
// The inner file should be wrapped (by `banner.start.js`) in a function that
// returns the AMD loader references.
diff --git a/src/collectedstatic/admin/js/vendor/select2/select2.full.min.js b/src/collectedstatic/admin/js/vendor/select2/select2.full.min.js
index fa78191..e4f98f1 100644
--- a/src/collectedstatic/admin/js/vendor/select2/select2.full.min.js
+++ b/src/collectedstatic/admin/js/vendor/select2/select2.full.min.js
@@ -1,2 +1,4 @@
/*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */
-!function(n){"function"==typeof define&&define.amd?define(["jquery"],n):"object"==typeof module&&module.exports?module.exports=function(e,t){return void 0===t&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),n(t),t}:n(jQuery)}(function(d){var e=function(){if(d&&d.fn&&d.fn.select2&&d.fn.select2.amd)var e=d.fn.select2.amd;var t,n,i,h,o,s,f,g,m,v,y,_,r,a,w,l;function b(e,t){return r.call(e,t)}function c(e,t){var n,i,r,o,s,a,l,c,u,d,p,h=t&&t.split("/"),f=y.map,g=f&&f["*"]||{};if(e){for(s=(e=e.split("/")).length-1,y.nodeIdCompat&&w.test(e[s])&&(e[s]=e[s].replace(w,"")),"."===e[0].charAt(0)&&h&&(e=h.slice(0,h.length-1).concat(e)),u=0;u '),e},n.prototype.bind=function(e,t){var i=this;n.__super__.bind.apply(this,arguments),this.$selection.on("click",function(e){i.trigger("toggle",{originalEvent:e})}),this.$selection.on("click",".select2-selection__choice__remove",function(e){if(!i.isDisabled()){var t=r(this).parent(),n=l.GetData(t[0],"data");i.trigger("unselect",{originalEvent:e,data:n})}})},n.prototype.clear=function(){var e=this.$selection.find(".select2-selection__rendered");e.empty(),e.removeAttr("title")},n.prototype.display=function(e,t){var n=this.options.get("templateSelection");return this.options.get("escapeMarkup")(n(e,t))},n.prototype.selectionContainer=function(){return r('