Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
Q
qiyouxue
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xuchentao
qiyouxue
Commits
6dc1c171
Commit
6dc1c171
authored
Aug 14, 2026
by
tao355667
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: refine contact UI and admin filters
parent
424c9f87
Changes
6
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
60 additions
and
23 deletions
+60
-23
app.js
public/admin/app.js
+19
-7
style.css
public/admin/style.css
+7
-0
ContactDialog.astro
src/components/ContactDialog.astro
+23
-8
Base.astro
src/layouts/Base.astro
+2
-2
index.astro
src/pages/admin/index.astro
+4
-1
global.css
src/styles/global.css
+5
-5
No files found.
public/admin/app.js
View file @
6dc1c171
...
@@ -15,6 +15,7 @@ let currentUser = null;
...
@@ -15,6 +15,7 @@ let currentUser = null;
let
consultationTeachers
=
[];
let
consultationTeachers
=
[];
let
staffAccounts
=
[];
let
staffAccounts
=
[];
let
activeConsultationUser
=
null
;
let
activeConsultationUser
=
null
;
let
articleRecords
=
[];
const
consultationStatusLabels
=
{
unprocessed
:
"未处理"
,
added
:
"已添加"
,
not_added
:
"未添加"
};
const
consultationStatusLabels
=
{
unprocessed
:
"未处理"
,
added
:
"已添加"
,
not_added
:
"未添加"
};
const
ADMIN_STATE_KEY
=
"qiyouxue-admin-state"
;
const
ADMIN_STATE_KEY
=
"qiyouxue-admin-state"
;
...
@@ -563,15 +564,16 @@ function applyStatus(element, status) {
...
@@ -563,15 +564,16 @@ function applyStatus(element, status) {
element.textContent = label;
element.textContent = label;
}
}
async function loadArticles() {
function renderArticles() {
const articles = await api("
/
articles
").catch((error) => { alert(error.message); return []; });
const list = $("
#
article
-
list
");
const list = $("
#
article
-
list
");
list.innerHTML = "";
list.innerHTML = "";
const pending = articles.filter((item) => item.publishStatus !== "
live
").length;
if (!articleRecords.length) { list.innerHTML = '<div class="
empty
">还没有文章,点击“新建文章”开始。</div>'; return; }
$("
#
pending
-
badge
").textContent = `${pending} 篇草稿待发布`;
const selectedStatus = $("
#
article
-
status
-
filter
").value;
$("
#
pending
-
badge
").classList.toggle("
hidden
", pending === 0);
const visibleArticles = selectedStatus === "
all
"
if (!articles.length) { list.innerHTML = '<div class="
empty
">还没有文章,点击“新建文章”开始。</div>'; return; }
? articleRecords
for (const article of articles) {
: articleRecords.filter((item) => item.publishStatus === selectedStatus);
if (!visibleArticles.length) { list.innerHTML = '<div class="
empty
">当前筛选条件下没有文章。</div>'; return; }
for (const article of visibleArticles) {
const card = document.createElement("
article
");
const card = document.createElement("
article
");
card.className = "
article
-
row
";
card.className = "
article
-
row
";
card.innerHTML = '<div class="
article
-
summary
"><h2></h2><p><span class="
category
"></span><span class="
updated
"></span><span class="
status
"></span></p></div><div class="
row
-
actions
"></div>';
card.innerHTML = '<div class="
article
-
summary
"><h2></h2><p><span class="
category
"></span><span class="
updated
"></span><span class="
status
"></span></p></div><div class="
row
-
actions
"></div>';
...
@@ -589,6 +591,16 @@ async function loadArticles() {
...
@@ -589,6 +591,16 @@ async function loadArticles() {
}
}
}
}
async function loadArticles() {
articleRecords = await api("
/
articles
").catch((error) => { alert(error.message); return []; });
const pending = articleRecords.filter((item) => item.publishStatus !== "
live
").length;
$("
#
pending
-
badge
").textContent = `${pending} 篇草稿待发布`;
$("
#
pending
-
badge
").classList.toggle("
hidden
", pending === 0);
renderArticles();
}
$("
#
article
-
status
-
filter
").addEventListener("
change
", renderArticles);
function listAction(label, className, action) {
function listAction(label, className, action) {
const button = document.createElement("
button
");
const button = document.createElement("
button
");
button.type = "
button
";
button.type = "
button
";
...
...
public/admin/style.css
View file @
6dc1c171
...
@@ -47,6 +47,10 @@ input:focus, textarea:focus, select:focus { outline: 2px solid rgba(20,115,230,.
...
@@ -47,6 +47,10 @@ input:focus, textarea:focus, select:focus { outline: 2px solid rgba(20,115,230,.
.view-head
p
{
margin
:
0
0
5px
;
color
:
var
(
--primary-dark
);
font-size
:
11px
;
font-weight
:
700
;
letter-spacing
:
.16em
;
}
.view-head
p
{
margin
:
0
0
5px
;
color
:
var
(
--primary-dark
);
font-size
:
11px
;
font-weight
:
700
;
letter-spacing
:
.16em
;
}
.view-head
h1
{
margin
:
0
;
font-size
:
30px
;
}
.view-head
h1
{
margin
:
0
;
font-size
:
30px
;
}
.view-actions
{
display
:
flex
;
gap
:
9px
;
}
.view-actions
{
display
:
flex
;
gap
:
9px
;
}
.article-toolbar
{
align-items
:
center
;
justify-content
:
space-between
;
gap
:
18px
;
}
.article-status-filter
{
display
:
flex
;
align-items
:
center
;
gap
:
9px
;
color
:
var
(
--muted
);
font-size
:
13px
;
}
.article-status-filter
>
span
{
white-space
:
nowrap
;
}
.article-status-filter
select
{
width
:
156px
;
min-height
:
40px
;
padding-block
:
8px
;
}
.import-status
{
min-height
:
20px
;
margin
:
-16px
0
12px
;
color
:
var
(
--muted
);
font-size
:
13px
;
text-align
:
right
;
}
.import-status
{
min-height
:
20px
;
margin
:
-16px
0
12px
;
color
:
var
(
--muted
);
font-size
:
13px
;
text-align
:
right
;
}
.article-list
{
display
:
grid
;
gap
:
10px
;
}
.article-list
{
display
:
grid
;
gap
:
10px
;
}
.article-row
{
padding
:
18px
20px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
gap
:
20px
;
background
:
white
;
border
:
1px
solid
var
(
--border
);
border-radius
:
14px
;
}
.article-row
{
padding
:
18px
20px
;
display
:
flex
;
align-items
:
center
;
justify-content
:
space-between
;
gap
:
20px
;
background
:
white
;
border
:
1px
solid
var
(
--border
);
border-radius
:
14px
;
}
...
@@ -182,6 +186,7 @@ input:focus, textarea:focus, select:focus { outline: 2px solid rgba(20,115,230,.
...
@@ -182,6 +186,7 @@ input:focus, textarea:focus, select:focus { outline: 2px solid rgba(20,115,230,.
.metric-grid
small
{
color
:
var
(
--muted
);
font-size
:
12px
;
}
.metric-grid
small
{
color
:
var
(
--muted
);
font-size
:
12px
;
}
.metric-grid
strong
{
color
:
#12365f
;
font-size
:
20px
;
}
.metric-grid
strong
{
color
:
#12365f
;
font-size
:
20px
;
}
.table-card
{
overflow-x
:
auto
;
overflow-y
:
hidden
;
background
:
white
;
border
:
1px
solid
var
(
--border
);
border-radius
:
10px
;
scrollbar-color
:
#b8c7d8
#f2f5f8
;
scrollbar-width
:
thin
;
}
.table-card
{
overflow-x
:
auto
;
overflow-y
:
hidden
;
background
:
white
;
border
:
1px
solid
var
(
--border
);
border-radius
:
10px
;
scrollbar-color
:
#b8c7d8
#f2f5f8
;
scrollbar-width
:
thin
;
}
.table-card
.empty
{
border
:
0
;
border-radius
:
0
;
}
.table-card
::-webkit-scrollbar
{
height
:
9px
;
}
.table-card
::-webkit-scrollbar
{
height
:
9px
;
}
.table-card
::-webkit-scrollbar-track
{
background
:
#f2f5f8
;
}
.table-card
::-webkit-scrollbar-track
{
background
:
#f2f5f8
;
}
.table-card
::-webkit-scrollbar-thumb
{
background
:
#b8c7d8
;
border
:
2px
solid
#f2f5f8
;
border-radius
:
999px
;
}
.table-card
::-webkit-scrollbar-thumb
{
background
:
#b8c7d8
;
border
:
2px
solid
#f2f5f8
;
border-radius
:
999px
;
}
...
@@ -283,6 +288,8 @@ input:focus, textarea:focus, select:focus { outline: 2px solid rgba(20,115,230,.
...
@@ -283,6 +288,8 @@ input:focus, textarea:focus, select:focus { outline: 2px solid rgba(20,115,230,.
@media
(
max-width
:
760px
)
{
@media
(
max-width
:
760px
)
{
.topbar
,
.view-head
,
.article-row
{
align-items
:
flex-start
;
flex-direction
:
column
;
}
.topbar
,
.view-head
,
.article-row
{
align-items
:
flex-start
;
flex-direction
:
column
;
}
.top-actions
{
width
:
100%
;
flex-wrap
:
wrap
;
}
.top-actions
{
width
:
100%
;
flex-wrap
:
wrap
;
}
.article-toolbar
{
align-items
:
stretch
;
flex-direction
:
column
;
}
.article-status-filter
{
justify-content
:
space-between
;
}
.view-actions
{
width
:
100%
;
}
.view-actions
{
width
:
100%
;
}
.view-actions
button
{
flex
:
1
;
}
.view-actions
button
{
flex
:
1
;
}
.field-row
,
.editor-grid
{
grid-template-columns
:
1
fr
;
}
.field-row
,
.editor-grid
{
grid-template-columns
:
1
fr
;
}
...
...
src/components/ContactDialog.astro
View file @
6dc1c171
...
@@ -22,16 +22,31 @@ import { site } from "../data/site";
...
@@ -22,16 +22,31 @@ import { site } from "../data/site";
<div class="contact-dialog__panel">
<div class="contact-dialog__panel">
<button class="contact-dialog__close" type="button" data-phone-dialog-close aria-label="关闭官方电话信息">×</button>
<button class="contact-dialog__close" type="button" data-phone-dialog-close aria-label="关闭官方电话信息">×</button>
<div class="phone-dialog__heading">
<div class="phone-dialog__heading">
<span>OFFICIAL CONTACT</span>
<h2 id="phone-dialog-title">官方联系方式</h2>
<h2 id="phone-dialog-title">官方电话</h2>
<p>课程咨询、服务反馈与商务合作,可通过以下官方渠道联系我们。</p>
<p>课程咨询、教师匹配与服务安排,欢迎致电了解。</p>
</div>
</div>
<a class="phone-dialog__number" href={`tel:${site.contact.phone}`}>{site.contact.phoneDisplay}</a>
<div class="official-contact-list">
<div class="phone-dialog__details">
<section class="official-contact-item official-contact-item--phone">
<span>服务时间:周一至周日 · 7×24 小时</span>
<span>客服电话</span>
<a href={`tel:${site.contact.phone}`}>{site.contact.phoneDisplay}</a>
<p>课程咨询与服务反馈</p>
</section>
<section class="official-contact-item">
<span>微信小程序</span>
<strong>启优学一对一</strong>
<p>搜索小程序名称提交预约</p>
</section>
<section class="official-contact-item">
<span>联系邮箱</span>
<a href={`mailto:${site.contact.email}`}>{site.contact.email}</a>
<a href={`mailto:${site.contact.email}`}>{site.contact.email}</a>
<p>商务合作与服务反馈</p>
</section>
<section class="official-contact-item">
<span>官方网站</span>
<a href={`https://${site.contact.website}`}>{site.contact.website}</a>
<p>官方课程与服务信息</p>
</section>
</div>
</div>
<a class="phone-dialog__call" href={`tel:${site.contact.phone}`}>立即拨打</a>
</div>
</div>
</dialog>
</dialog>
...
...
src/layouts/Base.astro
View file @
6dc1c171
This diff is collapsed.
Click to expand it.
src/pages/admin/index.astro
View file @
6dc1c171
...
@@ -66,7 +66,10 @@
...
@@ -66,7 +66,10 @@
</main>
</main>
<main
id=
"list-view"
class=
"view hidden content-role"
>
<main
id=
"list-view"
class=
"view hidden content-role"
>
<div
class=
"view-toolbar"
><div
class=
"view-actions"
><button
id=
"manage-categories"
class=
"ghost"
>
管理分类
</button><button
id=
"import-article"
class=
"ghost"
>
导入文件
</button><button
id=
"new-article"
class=
"primary"
>
+ 新建文章
</button></div></div>
<div
class=
"view-toolbar article-toolbar"
>
<label
class=
"article-status-filter"
for=
"article-status-filter"
><span>
发布状态
</span><select
id=
"article-status-filter"
aria-label=
"按发布状态筛选文章"
><option
value=
"all"
>
全部状态
</option><option
value=
"live"
>
已上线
</option><option
value=
"new-draft"
>
新建未发布
</option><option
value=
"edited-draft"
>
修改未发布
</option></select></label>
<div
class=
"view-actions"
><button
id=
"manage-categories"
class=
"ghost"
>
管理分类
</button><button
id=
"import-article"
class=
"ghost"
>
导入文件
</button><button
id=
"new-article"
class=
"primary"
>
+ 新建文章
</button></div>
</div>
<input
id=
"article-file"
class=
"hidden"
type=
"file"
accept=
".md,.docx,text/markdown,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
/>
<input
id=
"article-file"
class=
"hidden"
type=
"file"
accept=
".md,.docx,text/markdown,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
/>
<p
id=
"import-status"
class=
"import-status"
aria-live=
"polite"
></p>
<p
id=
"import-status"
class=
"import-status"
aria-live=
"polite"
></p>
<div
id=
"article-list"
class=
"article-list"
></div>
<div
id=
"article-list"
class=
"article-list"
></div>
...
...
src/styles/global.css
View file @
6dc1c171
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment