@@ -63,13 +63,22 @@ function statusLabel(status) {
|
|||||||
<div class="project-name">{{ p.name }}</div>
|
<div class="project-name">{{ p.name }}</div>
|
||||||
<div class="project-path">{{ p.path }}</div>
|
<div class="project-path">{{ p.path }}</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<div class="project-actions">
|
||||||
class="btn-edit"
|
<button
|
||||||
title="修改项目"
|
class="btn-icon"
|
||||||
@click="openEdit(p, $event)"
|
title="修改项目"
|
||||||
>
|
@click="openEdit(p, $event)"
|
||||||
<i class="fas fa-pen"></i>
|
>
|
||||||
</button>
|
<i class="fas fa-pen"></i>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="btn-icon btn-danger"
|
||||||
|
title="删除项目"
|
||||||
|
@click.stop="store.deleteProject(p.id)"
|
||||||
|
>
|
||||||
|
<i class="fas fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="project-status-row">
|
<div class="project-status-row">
|
||||||
<span class="status-badge" :class="statusClass(p.status)">{{ statusLabel(p.status) }}</span>
|
<span class="status-badge" :class="statusClass(p.status)">{{ statusLabel(p.status) }}</span>
|
||||||
@@ -156,8 +165,12 @@ function statusLabel(status) {
|
|||||||
border-left-color: var(--accent-blue);
|
border-left-color: var(--accent-blue);
|
||||||
}
|
}
|
||||||
.project-info { display: flex; align-items: center; gap: 0.5rem; }
|
.project-info { display: flex; align-items: center; gap: 0.5rem; }
|
||||||
.btn-edit {
|
.project-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.btn-icon {
|
||||||
width: 1.5rem;
|
width: 1.5rem;
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -172,7 +185,9 @@ function statusLabel(status) {
|
|||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
.btn-edit:hover { color: var(--accent-blue); background: var(--bg-secondary); opacity: 1; }
|
.btn-icon:hover { color: var(--accent-blue); background: var(--bg-secondary); opacity: 1; }
|
||||||
|
.btn-danger { color: #f97373; }
|
||||||
|
.btn-danger:hover { color: #f97373; background: rgba(248, 113, 113, 0.12); }
|
||||||
.folder-icon { color: var(--accent-blue); font-size: 0.875rem; }
|
.folder-icon { color: var(--accent-blue); font-size: 0.875rem; }
|
||||||
.project-meta { flex: 1; min-width: 0; }
|
.project-meta { flex: 1; min-width: 0; }
|
||||||
.project-name { font-size: 0.875rem; font-weight: 500; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
.project-name { font-size: 0.875rem; font-weight: 500; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||||
|
|||||||
@@ -34,7 +34,10 @@ export const useProjectsStore = defineStore('projects', () => {
|
|||||||
const selectedFilePath = ref(null)
|
const selectedFilePath = ref(null)
|
||||||
const fileContent = ref(null)
|
const fileContent = ref(null)
|
||||||
|
|
||||||
const current = computed(() => list.value.find(p => p.id === currentId.value) || null)
|
const current = computed(() => {
|
||||||
|
if (!Array.isArray(list.value)) return null
|
||||||
|
return list.value.find(p => p.id === currentId.value) || null
|
||||||
|
})
|
||||||
const rawFileTree = computed(() => statusData.value?.fileTree || null)
|
const rawFileTree = computed(() => statusData.value?.fileTree || null)
|
||||||
const currentFileTree = computed(() => {
|
const currentFileTree = computed(() => {
|
||||||
const tree = rawFileTree.value
|
const tree = rawFileTree.value
|
||||||
@@ -48,7 +51,7 @@ export const useProjectsStore = defineStore('projects', () => {
|
|||||||
error.value = null
|
error.value = null
|
||||||
try {
|
try {
|
||||||
const res = await projectsApi.list()
|
const res = await projectsApi.list()
|
||||||
list.value = res.data || []
|
list.value = Array.isArray(res.data) ? res.data : []
|
||||||
if (list.value.length && !currentId.value) {
|
if (list.value.length && !currentId.value) {
|
||||||
currentId.value = list.value[0].id
|
currentId.value = list.value[0].id
|
||||||
await refreshStatus()
|
await refreshStatus()
|
||||||
@@ -72,6 +75,19 @@ export const useProjectsStore = defineStore('projects', () => {
|
|||||||
return res.data
|
return res.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function deleteProject(id) {
|
||||||
|
if (!id) return
|
||||||
|
await projectsApi.delete(id)
|
||||||
|
// 重新加载列表并重置当前项目
|
||||||
|
await loadProjects()
|
||||||
|
if (!list.value.length) {
|
||||||
|
currentId.value = null
|
||||||
|
statusData.value = null
|
||||||
|
selectedFilePath.value = null
|
||||||
|
fileContent.value = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function refreshStatus() {
|
async function refreshStatus() {
|
||||||
if (!currentId.value) return
|
if (!currentId.value) return
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@@ -169,6 +185,7 @@ export const useProjectsStore = defineStore('projects', () => {
|
|||||||
loadProjects,
|
loadProjects,
|
||||||
addProject,
|
addProject,
|
||||||
updateProject,
|
updateProject,
|
||||||
|
deleteProject,
|
||||||
refreshStatus,
|
refreshStatus,
|
||||||
updateSvn,
|
updateSvn,
|
||||||
commit,
|
commit,
|
||||||
|
|||||||
Reference in New Issue
Block a user