1+ <!DOCTYPE html>
2+ < html lang ="zh ">
3+ < head >
4+ < meta charset ="UTF-8 ">
5+ < title > 资源接口管理后台</ title >
6+ < link href ="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.1.3/css/bootstrap.min.css " rel ="stylesheet ">
7+ < script src ="https://cdn.bootcdn.net/ajax/libs/vue/3.2.47/vue.global.prod.min.js "> </ script >
8+ </ head >
9+ < body class ="bg-light ">
10+
11+ < div id ="app " class ="container mt-5 ">
12+
13+ <!-- 登录界面 -->
14+ < div v-if ="!isLoggedIn " class ="card mx-auto shadow " style ="max-width: 400px; ">
15+ < div class ="card-body ">
16+ < h4 class ="card-title text-center mb-4 "> 管理员登录</ h4 >
17+ < div class ="mb-3 ">
18+ < input type ="password " v-model ="password " class ="form-control " placeholder ="请输入密码 (默认 admin) ">
19+ </ div >
20+ < button @click ="login " class ="btn btn-primary w-100 "> 登录</ button >
21+ </ div >
22+ </ div >
23+
24+ <!-- 管理界面 -->
25+ < div v-else >
26+ < div class ="d-flex justify-content-between align-items-center mb-4 ">
27+ < h3 > 接口源管理</ h3 >
28+ < div >
29+ < button class ="btn btn-success me-2 " @click ="addSite "> + 新增接口</ button >
30+ < button class ="btn btn-primary " @click ="saveSites "> 保存配置</ button >
31+ </ div >
32+ </ div >
33+
34+ < div class ="card shadow-sm ">
35+ < table class ="table table-hover mb-0 ">
36+ < thead class ="table-dark ">
37+ < tr >
38+ < th width ="10% "> 启用</ th >
39+ < th width ="15% "> 标识(Key)</ th >
40+ < th width ="20% "> 名称</ th >
41+ < th > API 地址 (Maccms V10)</ th >
42+ < th width ="15% "> 操作</ th >
43+ </ tr >
44+ </ thead >
45+ < tbody >
46+ < tr v-for ="(site, index) in sites " :key ="index ">
47+ < td >
48+ < div class ="form-check form-switch ">
49+ < input class ="form-check-input " type ="checkbox " v-model ="site.active ">
50+ </ div >
51+ </ td >
52+ < td > < input type ="text " v-model ="site.key " class ="form-control form-control-sm "> </ td >
53+ < td > < input type ="text " v-model ="site.name " class ="form-control form-control-sm "> </ td >
54+ < td > < input type ="text " v-model ="site.api " class ="form-control form-control-sm "> </ td >
55+ < td >
56+ < button class ="btn btn-danger btn-sm " @click ="removeSite(index) "> 删除</ button >
57+ </ td >
58+ </ tr >
59+ </ tbody >
60+ </ table >
61+ </ div >
62+ < div class ="mt-3 text-muted small ">
63+ 提示:修改后请点击右上角“保存配置”生效。后端会自动代理这些接口,前端用户无法查看到具体 URL。
64+ </ div >
65+ </ div >
66+ </ div >
67+
68+ < script >
69+ const { createApp } = Vue ;
70+ createApp ( {
71+ data ( ) {
72+ return {
73+ isLoggedIn : false ,
74+ password : '' ,
75+ sites : [ ]
76+ }
77+ } ,
78+ methods : {
79+ async login ( ) {
80+ const res = await fetch ( '/api/admin/login' , {
81+ method : 'POST' ,
82+ headers : { 'Content-Type' : 'application/json' } ,
83+ body : JSON . stringify ( { password : this . password } )
84+ } ) ;
85+ const data = await res . json ( ) ;
86+ if ( data . success ) {
87+ this . isLoggedIn = true ;
88+ this . fetchSites ( ) ;
89+ } else {
90+ alert ( data . msg ) ;
91+ }
92+ } ,
93+ async fetchSites ( ) {
94+ const res = await fetch ( '/api/admin/sites' ) ;
95+ this . sites = await res . json ( ) ;
96+ } ,
97+ addSite ( ) {
98+ this . sites . push ( { key : 'new' , name : '新资源' , api : '' , active : true } ) ;
99+ } ,
100+ removeSite ( index ) {
101+ if ( confirm ( '确定删除吗?' ) ) this . sites . splice ( index , 1 ) ;
102+ } ,
103+ async saveSites ( ) {
104+ const res = await fetch ( '/api/admin/sites' , {
105+ method : 'POST' ,
106+ headers : { 'Content-Type' : 'application/json' } ,
107+ body : JSON . stringify ( { sites : this . sites } )
108+ } ) ;
109+ alert ( '保存成功!' ) ;
110+ }
111+ }
112+ } ) . mount ( '#app' ) ;
113+ </ script >
114+ </ body >
115+ </ html >
0 commit comments