mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-22 16:43:35 +00:00
feat: 将admin-spa构建迁移到GitHub Actions workflow
🔄 主要改进: - 在自动发布流程中添加admin-spa前端构建步骤 - 仅在web/admin-spa目录有改动时才触发构建 - 构建后的dist目录会自动包含在版本发布中 - 移除手动提交的dist目录,避免安全风险 🐛 修复: - 修复登录后用户名显示为默认"Admin"的问题 - 现在会正确从服务器获取并显示实际用户名 🔒 安全优化: - 防止恶意代码通过dist目录注入 - 所有前端代码都会在CI环境中重新构建 现在开发者无需手动构建前端,workflow会自动处理 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
4
.github/cliff.toml
vendored
4
.github/cliff.toml
vendored
@@ -18,7 +18,7 @@ body = """
|
|||||||
{% for group, commits in commits | group_by(attribute="group") %}
|
{% for group, commits in commits | group_by(attribute="group") %}
|
||||||
### {{ group | upper_first }}
|
### {{ group | upper_first }}
|
||||||
{% for commit in commits %}
|
{% for commit in commits %}
|
||||||
- {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}](https://github.com/orhun/git-cliff/commit/{{ commit.id }}))
|
- {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}](https://github.com/Wei-Shaw/claude-relay-service/commit/{{ commit.id }}))
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
{% endfor %}\n
|
{% endfor %}\n
|
||||||
"""
|
"""
|
||||||
@@ -37,7 +37,7 @@ filter_unconventional = true
|
|||||||
split_commits = false
|
split_commits = false
|
||||||
# regex for preprocessing the commit messages
|
# regex for preprocessing the commit messages
|
||||||
commit_preprocessors = [
|
commit_preprocessors = [
|
||||||
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/orhun/git-cliff/issues/${2}))" },
|
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/Wei-Shaw/claude-relay-service/issues/${2}))" },
|
||||||
]
|
]
|
||||||
# regex for parsing and grouping commits
|
# regex for parsing and grouping commits
|
||||||
commit_parsers = [
|
commit_parsers = [
|
||||||
|
|||||||
59
.github/workflows/auto-release-pipeline.yml
vendored
59
.github/workflows/auto-release-pipeline.yml
vendored
@@ -103,6 +103,53 @@ jobs:
|
|||||||
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
||||||
echo "new_tag=v$NEW_VERSION" >> $GITHUB_OUTPUT
|
echo "new_tag=v$NEW_VERSION" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Check if frontend build is needed
|
||||||
|
id: check_frontend
|
||||||
|
if: steps.check.outputs.needs_bump == 'true'
|
||||||
|
run: |
|
||||||
|
# 检查 web/admin-spa 目录是否有变更
|
||||||
|
FRONTEND_CHANGES=false
|
||||||
|
CHANGED_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null || git diff --name-only $(git rev-list --max-parents=0 HEAD)..HEAD)
|
||||||
|
|
||||||
|
while IFS= read -r file; do
|
||||||
|
if [[ "$file" =~ ^web/admin-spa/ ]] &&
|
||||||
|
[[ ! "$file" =~ ^web/admin-spa/dist/ ]] &&
|
||||||
|
[[ ! "$file" =~ \.(md|txt)$ ]] &&
|
||||||
|
[[ "$file" != "web/admin-spa/.gitignore" ]]; then
|
||||||
|
echo "Found frontend change in: $file"
|
||||||
|
FRONTEND_CHANGES=true
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done <<< "$CHANGED_FILES"
|
||||||
|
|
||||||
|
echo "needs_build=$FRONTEND_CHANGES" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
if: steps.check.outputs.needs_bump == 'true' && steps.check_frontend.outputs.needs_build == 'true'
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '18'
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: web/admin-spa/package-lock.json
|
||||||
|
|
||||||
|
- name: Build admin-spa
|
||||||
|
if: steps.check.outputs.needs_bump == 'true' && steps.check_frontend.outputs.needs_build == 'true'
|
||||||
|
run: |
|
||||||
|
echo "Building admin-spa frontend..."
|
||||||
|
cd web/admin-spa
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
cd ../..
|
||||||
|
|
||||||
|
# 确认 dist 目录已创建
|
||||||
|
if [ -d "web/admin-spa/dist" ]; then
|
||||||
|
echo "✅ Frontend build successful"
|
||||||
|
ls -la web/admin-spa/dist/
|
||||||
|
else
|
||||||
|
echo "❌ Frontend build failed - dist directory not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Update VERSION file
|
- name: Update VERSION file
|
||||||
if: steps.check.outputs.needs_bump == 'true'
|
if: steps.check.outputs.needs_bump == 'true'
|
||||||
run: |
|
run: |
|
||||||
@@ -112,9 +159,19 @@ jobs:
|
|||||||
git config user.name "github-actions[bot]"
|
git config user.name "github-actions[bot]"
|
||||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
# 提交VERSION文件 - 添加 [skip ci] 以避免再次触发
|
# 检查是否需要添加 dist 目录
|
||||||
|
if [ "${{ steps.check_frontend.outputs.needs_build }}" = "true" ] && [ -d "web/admin-spa/dist" ]; then
|
||||||
|
git add -f web/admin-spa/dist/
|
||||||
|
echo "Added frontend dist directory to commit"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 提交VERSION文件和可能的dist目录 - 添加 [skip ci] 以避免再次触发
|
||||||
git add VERSION
|
git add VERSION
|
||||||
|
if [ "${{ steps.check_frontend.outputs.needs_build }}" = "true" ]; then
|
||||||
|
git commit -m "chore: sync VERSION file with release ${{ steps.next_version.outputs.new_tag }} and rebuild frontend [skip ci]"
|
||||||
|
else
|
||||||
git commit -m "chore: sync VERSION file with release ${{ steps.next_version.outputs.new_tag }} [skip ci]"
|
git commit -m "chore: sync VERSION file with release ${{ steps.next_version.outputs.new_tag }} [skip ci]"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Install git-cliff
|
- name: Install git-cliff
|
||||||
if: steps.check.outputs.needs_bump == 'true'
|
if: steps.check.outputs.needs_bump == 'true'
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
.accounts-container[data-v-1665099c]{min-height:calc(100vh - 300px)}.table-container[data-v-1665099c]{overflow-x:auto;border-radius:12px;border:1px solid rgba(0,0,0,.05)}.table-row[data-v-1665099c]{transition:all .2s ease}.table-row[data-v-1665099c]:hover{background-color:#00000005}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
pre[data-v-747f035b]{white-space:pre-wrap;word-wrap:break-word}.tab-content[data-v-b60a91aa]{min-height:calc(100vh - 300px)}.table-container[data-v-b60a91aa]{overflow-x:auto;border-radius:12px;border:1px solid rgba(0,0,0,.05)}.table-row[data-v-b60a91aa]{transition:all .2s ease}.table-row[data-v-b60a91aa]:hover{background-color:#00000005}.loading-spinner[data-v-b60a91aa]{width:24px;height:24px;border:2px solid #e5e7eb;border-top:2px solid #3b82f6;border-radius:50%;animation:spin-b60a91aa 1s linear infinite}@keyframes spin-b60a91aa{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.api-key-date-picker[data-v-b60a91aa] .el-input__inner{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.api-key-date-picker[data-v-b60a91aa] .el-input__inner:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.api-key-date-picker[data-v-b60a91aa] .el-range-separator{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
.custom-date-picker[data-v-5170898f] .el-input__inner{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.custom-date-picker[data-v-5170898f] .el-input__inner:focus{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.custom-date-picker[data-v-5170898f] .el-input__inner{font-size:13px;padding:0 10px}.custom-date-picker[data-v-5170898f] .el-range-separator{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1));padding:0 2px}.custom-date-picker[data-v-5170898f] .el-range-input{font-size:13px}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
import{c as b,r as x,q as f,x as a,z as s,L as i,Q as y,u as o,P as m,Y as _,K as u,aq as c,O as g,y as n}from"./vue-vendor-YmkKLAOK.js";import{_ as v,u as w}from"./index-15K8yWyh.js";/* empty css */import"./element-plus-D-FTEVKS.js";import"./vendor-BDiMbLwQ.js";const h={class:"flex items-center justify-center min-h-screen p-6"},k={class:"glass-strong rounded-3xl p-10 w-full max-w-md shadow-2xl"},L={class:"text-center mb-8"},S={class:"w-20 h-20 mx-auto mb-6 bg-gradient-to-br from-blue-500/20 to-purple-500/20 border border-gray-300/30 rounded-2xl flex items-center justify-center backdrop-blur-sm overflow-hidden"},V=["src"],I={key:1,class:"fas fa-cloud text-3xl text-gray-700"},N={key:1,class:"w-12 h-12 bg-gray-300/50 rounded animate-pulse"},q={key:0,class:"text-3xl font-bold text-white mb-2 header-title"},D={key:1,class:"h-9 w-64 bg-gray-300/50 rounded animate-pulse mx-auto mb-2"},E=["disabled"],j={key:0,class:"fas fa-sign-in-alt mr-2"},B={key:1,class:"loading-spinner mr-2"},M={key:0,class:"mt-6 p-4 bg-red-500/20 border border-red-500/30 rounded-xl text-red-800 text-sm text-center backdrop-blur-sm"},F={__name:"LoginView",setup(O){const e=w(),d=b(()=>e.oemLoading),l=x({username:"",password:""});f(()=>{e.loadOemSettings()});const p=async()=>{await e.login(l.value)};return(T,t)=>(n(),a("div",h,[s("div",k,[s("div",L,[s("div",S,[d.value?(n(),a("div",N)):(n(),a(y,{key:0},[o(e).oemSettings.siteIconData||o(e).oemSettings.siteIcon?(n(),a("img",{key:0,src:o(e).oemSettings.siteIconData||o(e).oemSettings.siteIcon,alt:"Logo",class:"w-12 h-12 object-contain",onError:t[0]||(t[0]=r=>r.target.style.display="none")},null,40,V)):(n(),a("i",I))],64))]),!d.value&&o(e).oemSettings.siteName?(n(),a("h1",q,m(o(e).oemSettings.siteName),1)):d.value?(n(),a("div",D)):i("",!0),t[3]||(t[3]=s("p",{class:"text-gray-600 text-lg"},"管理后台",-1))]),s("form",{onSubmit:_(p,["prevent"]),class:"space-y-6"},[s("div",null,[t[4]||(t[4]=s("label",{class:"block text-sm font-semibold text-gray-900 mb-3"},"用户名",-1)),u(s("input",{"onUpdate:modelValue":t[1]||(t[1]=r=>l.value.username=r),type:"text",required:"",class:"form-input w-full",placeholder:"请输入用户名"},null,512),[[c,l.value.username]])]),s("div",null,[t[5]||(t[5]=s("label",{class:"block text-sm font-semibold text-gray-900 mb-3"},"密码",-1)),u(s("input",{"onUpdate:modelValue":t[2]||(t[2]=r=>l.value.password=r),type:"password",required:"",class:"form-input w-full",placeholder:"请输入密码"},null,512),[[c,l.value.password]])]),s("button",{type:"submit",disabled:o(e).loginLoading,class:"btn btn-primary w-full py-4 px-6 text-lg font-semibold"},[o(e).loginLoading?i("",!0):(n(),a("i",j)),o(e).loginLoading?(n(),a("div",B)):i("",!0),g(" "+m(o(e).loginLoading?"登录中...":"登录"),1)],8,E)],32),o(e).loginError?(n(),a("div",M,[t[6]||(t[6]=s("i",{class:"fas fa-exclamation-triangle mr-2"},null,-1)),g(m(o(e).loginError),1)])):i("",!0)])]))}},P=v(F,[["__scopeId","data-v-4a19afbe"]]);export{P as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/* empty css */import{_ as r}from"./index-15K8yWyh.js";import{x as e,y as s,z as o,Q as c,L as l,C as d,P as i}from"./vue-vendor-YmkKLAOK.js";const g={class:"flex items-center gap-4"},u={class:"w-12 h-12 bg-gradient-to-br from-blue-500/20 to-purple-500/20 border border-gray-300/30 rounded-xl flex items-center justify-center backdrop-blur-sm flex-shrink-0 overflow-hidden"},y=["src"],f={key:1,class:"fas fa-cloud text-xl text-gray-700"},m={key:1,class:"w-8 h-8 bg-gray-300/50 rounded animate-pulse"},h={class:"flex flex-col justify-center min-h-[48px]"},x={class:"flex items-center gap-3"},b={key:1,class:"h-8 w-64 bg-gray-300/50 rounded animate-pulse"},k={key:0,class:"text-gray-600 text-sm leading-tight mt-0.5"},_={__name:"LogoTitle",props:{loading:{type:Boolean,default:!1},title:{type:String,default:""},subtitle:{type:String,default:""},logoSrc:{type:String,default:""},titleClass:{type:String,default:"text-gray-900"}},setup(t){const n=a=>{a.target.style.display="none"};return(a,p)=>(s(),e("div",g,[o("div",u,[t.loading?(s(),e("div",m)):(s(),e(c,{key:0},[t.logoSrc?(s(),e("img",{key:0,src:t.logoSrc,alt:"Logo",class:"w-8 h-8 object-contain",onError:n},null,40,y)):(s(),e("i",f))],64))]),o("div",h,[o("div",x,[!t.loading&&t.title?(s(),e("h1",{key:0,class:d(["text-2xl font-bold header-title leading-tight",t.titleClass])},i(t.title),3)):t.loading?(s(),e("div",b)):l("",!0)]),t.subtitle?(s(),e("p",k,i(t.subtitle),1)):l("",!0)])]))}},w=r(_,[["__scopeId","data-v-43271b76"]]);export{w as L};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
@keyframes pulse-43271b76{0%{opacity:.7}50%{opacity:.4}to{opacity:.7}}.animate-pulse[data-v-43271b76]{animation:pulse-43271b76 2s cubic-bezier(.4,0,.6,1) infinite}.header-title[data-v-43271b76]{text-shadow:0 1px 2px rgba(0,0,0,.1)}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
.user-menu-dropdown[data-v-9f4a7654]{margin-top:8px}.fade-enter-active[data-v-9f4a7654],.fade-leave-active[data-v-9f4a7654]{transition:opacity .3s}.fade-enter-from[data-v-9f4a7654],.fade-leave-to[data-v-9f4a7654]{opacity:0}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,3 +0,0 @@
|
|||||||
import{aR as k,r as x,aW as C,q as O,x as m,z as e,u as i,K as T,aq as N,L as _,O as v,C as j,P as S,y as g}from"./vue-vendor-YmkKLAOK.js";import{s as c}from"./toast-BvwA7Mwb.js";import{a as D,_ as F}from"./index-15K8yWyh.js";import"./element-plus-D-FTEVKS.js";import"./vendor-BDiMbLwQ.js";const E=k("settings",()=>{const l=x({siteName:"Claude Relay Service",siteIcon:"",siteIconData:"",updatedAt:null}),r=x(!1),p=x(!1),d=async()=>{r.value=!0;try{const s=await D.get("/admin/oem-settings");return s&&s.success&&(l.value={...l.value,...s.data},f()),s}catch(s){throw console.error("Failed to load OEM settings:",s),s}finally{r.value=!1}},a=async s=>{p.value=!0;try{const o=await D.put("/admin/oem-settings",s);return o&&o.success&&(l.value={...l.value,...o.data},f()),o}catch(o){throw console.error("Failed to save OEM settings:",o),o}finally{p.value=!1}},w=async()=>{const s={siteName:"Claude Relay Service",siteIcon:"",siteIconData:"",updatedAt:null};return l.value={...s},await a(s)},f=()=>{if(l.value.siteName&&(document.title=`${l.value.siteName} - 管理后台`),l.value.siteIconData||l.value.siteIcon){const s=document.querySelector('link[rel="icon"]')||document.createElement("link");s.rel="icon",s.href=l.value.siteIconData||l.value.siteIcon,document.querySelector('link[rel="icon"]')||document.head.appendChild(s)}};return{oemSettings:l,loading:r,saving:p,loadOemSettings:d,saveOemSettings:a,resetOemSettings:w,applyOemSettings:f,formatDateTime:s=>s?new Date(s).toLocaleString("zh-CN",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"}):"",validateIconFile:s=>{const o=[];return s.size>350*1024&&o.push("图标文件大小不能超过 350KB"),["image/x-icon","image/png","image/jpeg","image/jpg","image/svg+xml"].includes(s.type)||o.push("不支持的文件类型,请选择 .ico, .png, .jpg 或 .svg 文件"),{isValid:o.length===0,errors:o}},fileToBase64:s=>new Promise((o,n)=>{const t=new FileReader;t.onload=u=>o(u.target.result),t.onerror=n,t.readAsDataURL(s)})}}),B={class:"settings-container"},V={class:"card p-6"},R={key:0,class:"text-center py-12"},M={key:1,class:"table-container"},A={class:"min-w-full"},q={class:"divide-y divide-gray-200/50"},z={class:"table-row"},K={class:"px-6 py-4"},L={class:"table-row"},U={class:"px-6 py-4"},$={class:"space-y-3"},P={key:0,class:"inline-flex items-center gap-3 p-3 bg-gray-50 rounded-lg"},W=["src"],G={class:"px-6 py-6",colspan:"2"},H={class:"flex items-center justify-between"},J={class:"flex gap-3"},Q=["disabled"],X={key:0,class:"loading-spinner mr-2"},Y={key:1,class:"fas fa-save mr-2"},Z=["disabled"],ee={key:0,class:"text-sm text-gray-500"},te={__name:"SettingsView",setup(l){const r=E(),{loading:p,saving:d,oemSettings:a}=C(r),w=x();O(async()=>{try{await r.loadOemSettings()}catch{c("加载设置失败","error")}});const f=async()=>{try{const n={siteName:a.value.siteName,siteIcon:a.value.siteIcon,siteIconData:a.value.siteIconData},t=await r.saveOemSettings(n);t&&t.success?c("OEM设置保存成功","success"):c((t==null?void 0:t.message)||"保存失败","error")}catch{c("保存OEM设置失败","error")}},b=async()=>{if(confirm(`确定要重置为默认设置吗?
|
|
||||||
|
|
||||||
这将清除所有自定义的网站名称和图标设置。`))try{const n=await r.resetOemSettings();n&&n.success?c("已重置为默认设置","success"):c("重置失败","error")}catch{c("重置失败","error")}},h=async n=>{const t=n.target.files[0];if(!t)return;const u=r.validateIconFile(t);if(!u.isValid){u.errors.forEach(y=>c(y,"error"));return}try{const y=await r.fileToBase64(t);a.value.siteIconData=y}catch{c("文件读取失败","error")}n.target.value=""},I=()=>{a.value.siteIcon="",a.value.siteIconData=""},s=()=>{console.warn("Icon failed to load")},o=r.formatDateTime;return(n,t)=>(g(),m("div",B,[e("div",V,[t[12]||(t[12]=e("div",{class:"flex flex-col md:flex-row justify-between items-center gap-4 mb-6"},[e("div",null,[e("h3",{class:"text-xl font-bold text-gray-900 mb-2"},"其他设置"),e("p",{class:"text-gray-600"},"自定义网站名称和图标")])],-1)),i(p)?(g(),m("div",R,t[2]||(t[2]=[e("div",{class:"loading-spinner mx-auto mb-4"},null,-1),e("p",{class:"text-gray-500"},"正在加载设置...",-1)]))):(g(),m("div",M,[e("table",A,[e("tbody",q,[e("tr",z,[t[4]||(t[4]=e("td",{class:"px-6 py-4 whitespace-nowrap w-48"},[e("div",{class:"flex items-center"},[e("div",{class:"w-8 h-8 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center mr-3"},[e("i",{class:"fas fa-font text-white text-xs"})]),e("div",null,[e("div",{class:"text-sm font-semibold text-gray-900"},"网站名称"),e("div",{class:"text-xs text-gray-500"},"品牌标识")])])],-1)),e("td",K,[T(e("input",{"onUpdate:modelValue":t[0]||(t[0]=u=>i(a).siteName=u),type:"text",class:"form-input w-full max-w-md",placeholder:"Claude Relay Service",maxlength:"100"},null,512),[[N,i(a).siteName]]),t[3]||(t[3]=e("p",{class:"text-xs text-gray-500 mt-1"},"将显示在浏览器标题和页面头部",-1))])]),e("tr",L,[t[9]||(t[9]=e("td",{class:"px-6 py-4 whitespace-nowrap w-48"},[e("div",{class:"flex items-center"},[e("div",{class:"w-8 h-8 bg-gradient-to-br from-purple-500 to-purple-600 rounded-lg flex items-center justify-center mr-3"},[e("i",{class:"fas fa-image text-white text-xs"})]),e("div",null,[e("div",{class:"text-sm font-semibold text-gray-900"},"网站图标"),e("div",{class:"text-xs text-gray-500"},"Favicon")])])],-1)),e("td",U,[e("div",$,[i(a).siteIconData||i(a).siteIcon?(g(),m("div",P,[e("img",{src:i(a).siteIconData||i(a).siteIcon,alt:"图标预览",class:"w-8 h-8",onError:s},null,40,W),t[6]||(t[6]=e("span",{class:"text-sm text-gray-600"},"当前图标",-1)),e("button",{onClick:I,class:"text-red-600 hover:text-red-900 font-medium hover:bg-red-50 px-3 py-1 rounded-lg transition-colors"},t[5]||(t[5]=[e("i",{class:"fas fa-trash mr-1"},null,-1),v("删除 ",-1)]))])):_("",!0),e("div",null,[e("input",{type:"file",ref_key:"iconFileInput",ref:w,onChange:h,accept:".ico,.png,.jpg,.jpeg,.svg",class:"hidden"},null,544),e("button",{onClick:t[1]||(t[1]=u=>n.$refs.iconFileInput.click()),class:"btn btn-success px-4 py-2"},t[7]||(t[7]=[e("i",{class:"fas fa-upload mr-2"},null,-1),v(" 上传图标 ",-1)])),t[8]||(t[8]=e("span",{class:"text-xs text-gray-500 ml-3"},"支持 .ico, .png, .jpg, .svg 格式,最大 350KB",-1))])])])]),e("tr",null,[e("td",G,[e("div",H,[e("div",J,[e("button",{onClick:f,disabled:i(d),class:j(["btn btn-primary px-6 py-3",{"opacity-50 cursor-not-allowed":i(d)}])},[i(d)?(g(),m("div",X)):(g(),m("i",Y)),v(" "+S(i(d)?"保存中...":"保存设置"),1)],10,Q),e("button",{onClick:b,class:"btn bg-gray-100 text-gray-700 hover:bg-gray-200 px-6 py-3",disabled:i(d)},t[10]||(t[10]=[e("i",{class:"fas fa-undo mr-2"},null,-1),v(" 重置为默认 ",-1)]),8,Z)]),i(a).updatedAt?(g(),m("div",ee,[t[11]||(t[11]=e("i",{class:"fas fa-clock mr-1"},null,-1)),v(" 最后更新:"+S(i(o)(i(a).updatedAt)),1)])):_("",!0)])])])])])]))])]))}},le=F(te,[["__scopeId","data-v-3508e0de"]]);export{le as default};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
.settings-container[data-v-3508e0de]{min-height:calc(100vh - 300px)}.card[data-v-3508e0de]{background:#fff;border-radius:12px;box-shadow:0 2px 12px #0000001a;border:1px solid #e5e7eb}.table-container[data-v-3508e0de]{overflow:hidden;border-radius:8px;border:1px solid #f3f4f6}.table-row[data-v-3508e0de]{transition:background-color .2s ease}.table-row[data-v-3508e0de]:hover{background-color:#f9fafb}.form-input[data-v-3508e0de]{width:100%;border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));padding:.5rem 1rem;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.form-input[data-v-3508e0de]:focus{border-color:transparent;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.btn[data-v-3508e0de]{display:inline-flex;align-items:center;justify-content:center;border-radius:.5rem;padding:.5rem 1rem;font-size:.875rem;line-height:1.25rem;font-weight:600;transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.btn[data-v-3508e0de]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-offset-width: 2px}.btn-primary[data-v-3508e0de]{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-primary[data-v-3508e0de]:hover{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity, 1))}.btn-primary[data-v-3508e0de]:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity, 1))}.btn-success[data-v-3508e0de]{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.btn-success[data-v-3508e0de]:hover{--tw-bg-opacity: 1;background-color:rgb(21 128 61 / var(--tw-bg-opacity, 1))}.btn-success[data-v-3508e0de]:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(34 197 94 / var(--tw-ring-opacity, 1))}.loading-spinner[data-v-3508e0de]{height:1.25rem;width:1.25rem}@keyframes spin-3508e0de{to{transform:rotate(360deg)}}.loading-spinner[data-v-3508e0de]{animation:spin-3508e0de 1s linear infinite;border-radius:9999px;border-width:2px;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));--tw-border-opacity: 1;border-top-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1 +0,0 @@
|
|||||||
.tutorial-container[data-v-58e5d8f5]{min-height:calc(100vh - 300px)}.tutorial-content[data-v-58e5d8f5]{animation:fadeIn-58e5d8f5 .3s ease-in-out}@keyframes fadeIn-58e5d8f5{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}code[data-v-58e5d8f5]{font-family:Fira Code,Monaco,Menlo,Ubuntu Mono,monospace}.tutorial-content h4[data-v-58e5d8f5]{scroll-margin-top:100px}.tutorial-content .bg-gradient-to-r[data-v-58e5d8f5]{transition:all .2s ease}.tutorial-content .bg-gradient-to-r[data-v-58e5d8f5]:hover{transform:translateY(-1px);box-shadow:0 4px 12px #0000001a}
|
|
||||||
13
web/admin-spa/dist/assets/chart-Cor9iTVD.js
vendored
13
web/admin-spa/dist/assets/chart-Cor9iTVD.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
web/admin-spa/dist/assets/fa-brands-400-D1LuMI3I.ttf
vendored
BIN
web/admin-spa/dist/assets/fa-brands-400-D1LuMI3I.ttf
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
web/admin-spa/dist/assets/fa-solid-900-D0aA9rwL.ttf
vendored
BIN
web/admin-spa/dist/assets/fa-solid-900-D0aA9rwL.ttf
vendored
Binary file not shown.
Binary file not shown.
Binary file not shown.
2
web/admin-spa/dist/assets/index-15K8yWyh.js
vendored
2
web/admin-spa/dist/assets/index-15K8yWyh.js
vendored
File diff suppressed because one or more lines are too long
5
web/admin-spa/dist/assets/index-BDHMSjjg.css
vendored
5
web/admin-spa/dist/assets/index-BDHMSjjg.css
vendored
File diff suppressed because one or more lines are too long
22
web/admin-spa/dist/assets/toast-BvwA7Mwb.js
vendored
22
web/admin-spa/dist/assets/toast-BvwA7Mwb.js
vendored
@@ -1,22 +0,0 @@
|
|||||||
let e=null,r=0;function c(n,s="info",a="",i=3e3){e||(e=document.createElement("div"),e.id="toast-container",e.style.cssText="position: fixed; top: 20px; right: 20px; z-index: 10000;",document.body.appendChild(e));const o=++r,t=document.createElement("div");t.className=`toast rounded-2xl p-4 shadow-2xl backdrop-blur-sm toast-${s}`,t.style.cssText=`
|
|
||||||
position: relative;
|
|
||||||
min-width: 320px;
|
|
||||||
max-width: 500px;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
transform: translateX(100%);
|
|
||||||
transition: transform 0.3s ease-in-out;
|
|
||||||
`;const l={success:"fas fa-check-circle",error:"fas fa-times-circle",warning:"fas fa-exclamation-triangle",info:"fas fa-info-circle"};return t.innerHTML=`
|
|
||||||
<div class="flex items-start gap-3">
|
|
||||||
<div class="flex-shrink-0 mt-0.5">
|
|
||||||
<i class="${l[s]} text-lg"></i>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 min-w-0">
|
|
||||||
${a?`<h4 class="font-semibold text-sm mb-1">${a}</h4>`:""}
|
|
||||||
<p class="text-sm opacity-90 leading-relaxed">${n}</p>
|
|
||||||
</div>
|
|
||||||
<button onclick="this.parentElement.parentElement.remove()"
|
|
||||||
class="flex-shrink-0 text-white/70 hover:text-white transition-colors ml-2">
|
|
||||||
<i class="fas fa-times"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
`,e.appendChild(t),setTimeout(()=>{t.style.transform="translateX(0)"},10),i>0&&setTimeout(()=>{t.style.transform="translateX(100%)",setTimeout(()=>{t.remove()},300)},i),o}export{c as s};
|
|
||||||
30
web/admin-spa/dist/assets/vendor-BDiMbLwQ.js
vendored
30
web/admin-spa/dist/assets/vendor-BDiMbLwQ.js
vendored
File diff suppressed because one or more lines are too long
25
web/admin-spa/dist/assets/vue-vendor-YmkKLAOK.js
vendored
25
web/admin-spa/dist/assets/vue-vendor-YmkKLAOK.js
vendored
File diff suppressed because one or more lines are too long
31
web/admin-spa/dist/index.html
vendored
31
web/admin-spa/dist/index.html
vendored
@@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="zh-CN">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Claude Relay Service - 管理后台</title>
|
|
||||||
|
|
||||||
<!-- Google Fonts -->
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
||||||
|
|
||||||
<!-- Font Awesome -->
|
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
||||||
|
|
||||||
<!-- 预连接到CDN域名,加速资源加载 -->
|
|
||||||
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
|
|
||||||
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
|
|
||||||
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net">
|
|
||||||
<link rel="dns-prefetch" href="https://cdnjs.cloudflare.com">
|
|
||||||
<script type="module" crossorigin src="/admin-next/assets/index-15K8yWyh.js"></script>
|
|
||||||
<link rel="modulepreload" crossorigin href="/admin-next/assets/vue-vendor-YmkKLAOK.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/admin-next/assets/vendor-BDiMbLwQ.js">
|
|
||||||
<link rel="modulepreload" crossorigin href="/admin-next/assets/element-plus-D-FTEVKS.js">
|
|
||||||
<link rel="stylesheet" crossorigin href="/admin-next/assets/element-plus-CPnoEkWW.css">
|
|
||||||
<link rel="stylesheet" crossorigin href="/admin-next/assets/index-BDHMSjjg.css">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -33,7 +33,7 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
authToken.value = result.token
|
authToken.value = result.token
|
||||||
username.value = credentials.username
|
username.value = result.username || credentials.username
|
||||||
isLoggedIn.value = true
|
isLoggedIn.value = true
|
||||||
localStorage.setItem('authToken', result.token)
|
localStorage.setItem('authToken', result.token)
|
||||||
|
|
||||||
@@ -66,6 +66,12 @@ export const useAuthStore = defineStore('auth', () => {
|
|||||||
|
|
||||||
async function verifyToken() {
|
async function verifyToken() {
|
||||||
try {
|
try {
|
||||||
|
// 获取当前用户信息
|
||||||
|
const userResult = await apiClient.get('/web/auth/user')
|
||||||
|
if (userResult.success && userResult.user) {
|
||||||
|
username.value = userResult.user.username
|
||||||
|
}
|
||||||
|
|
||||||
// 使用 dashboard 端点来验证 token
|
// 使用 dashboard 端点来验证 token
|
||||||
// 如果 token 无效,会抛出错误
|
// 如果 token 无效,会抛出错误
|
||||||
const result = await apiClient.get('/admin/dashboard')
|
const result = await apiClient.get('/admin/dashboard')
|
||||||
|
|||||||
Reference in New Issue
Block a user