This commit is contained in:
root 2025-07-11 01:15:23 +08:00
parent a9b411bc41
commit d6dd6109c0
2 changed files with 72 additions and 127 deletions

View File

@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import { Plus, Edit, Trash2, Search, Save, X, FolderOpen, Package } from 'lucide-react' import { Plus, Edit, Trash2, Search, Save, X, FolderOpen, Package } from 'lucide-react'
import { open } from '@tauri-apps/plugin-dialog'
import { ProjectService, Project } from '../services/projectService' import { ProjectService, Project } from '../services/projectService'
const ProjectManagePage: React.FC = () => { const ProjectManagePage: React.FC = () => {
@ -100,9 +101,13 @@ const ProjectManagePage: React.FC = () => {
const selectDirectory = async () => { const selectDirectory = async () => {
try { try {
// TODO: 使用Tauri的文件选择器 const directory = await open({
const directory = prompt('请输入项目目录路径:') directory: true,
if (directory) { multiple: false,
title: '选择项目目录'
})
if (directory && typeof directory === 'string') {
setFormData({ ...formData, local_directory: directory }) setFormData({ ...formData, local_directory: directory })
} }
} catch (error) { } catch (error) {
@ -112,9 +117,18 @@ const ProjectManagePage: React.FC = () => {
const selectImage = async () => { const selectImage = async () => {
try { try {
// TODO: 使用Tauri的文件选择器 const imagePath = await open({
const imagePath = prompt('请输入商品图片路径:') multiple: false,
if (imagePath) { title: '选择商品图片',
filters: [
{
name: '图片文件',
extensions: ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp', 'svg']
}
]
})
if (imagePath && typeof imagePath === 'string') {
setFormData({ ...formData, product_image: imagePath }) setFormData({ ...formData, product_image: imagePath })
} }
} catch (error) { } catch (error) {
@ -319,14 +333,17 @@ const ProjectManagePage: React.FC = () => {
type="text" type="text"
value={formData.local_directory} value={formData.local_directory}
onChange={(e) => setFormData({ ...formData, local_directory: e.target.value })} onChange={(e) => setFormData({ ...formData, local_directory: e.target.value })}
placeholder="请选择或输入项目目录路径" placeholder="请选择项目目录路径"
className="flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
readOnly
/> />
<button <button
onClick={selectDirectory} onClick={selectDirectory}
className="px-3 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors" className="px-4 py-2 bg-blue-100 text-blue-700 rounded-lg hover:bg-blue-200 transition-colors flex items-center space-x-1"
title="选择目录"
> >
<FolderOpen size={16} /> <FolderOpen size={16} />
<span className="text-sm"></span>
</button> </button>
</div> </div>
</div> </div>
@ -355,16 +372,40 @@ const ProjectManagePage: React.FC = () => {
type="text" type="text"
value={formData.product_image} value={formData.product_image}
onChange={(e) => setFormData({ ...formData, product_image: e.target.value })} onChange={(e) => setFormData({ ...formData, product_image: e.target.value })}
placeholder="请选择或输入商品图片路径" placeholder="请选择商品图片文件"
className="flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent" className="flex-1 px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
readOnly
/> />
<button <button
onClick={selectImage} onClick={selectImage}
className="px-3 py-2 bg-gray-100 text-gray-700 rounded-lg hover:bg-gray-200 transition-colors" className="px-4 py-2 bg-green-100 text-green-700 rounded-lg hover:bg-green-200 transition-colors flex items-center space-x-1"
title="选择图片"
> >
<Package size={16} /> <Package size={16} />
<span className="text-sm"></span>
</button> </button>
</div> </div>
{/* 图片预览 */}
{formData.product_image && (
<div className="mt-2">
<p className="text-xs text-gray-500 mb-1">:</p>
<div className="w-20 h-20 border border-gray-200 rounded-lg overflow-hidden bg-gray-50 flex items-center justify-center">
<img
src={`file://${formData.product_image}`}
alt="商品图片预览"
className="w-full h-full object-cover"
onError={(e) => {
const target = e.target as HTMLImageElement
target.style.display = 'none'
target.nextElementSibling!.classList.remove('hidden')
}}
/>
<div className="hidden text-xs text-gray-400 text-center p-2">
</div>
</div>
</div>
)}
</div> </div>
</div> </div>

View File

@ -37,28 +37,9 @@ export class ProjectService {
*/ */
static async getAllProjects(): Promise<ApiResponse<Project[]>> { static async getAllProjects(): Promise<ApiResponse<Project[]>> {
try { try {
console.log('Calling get_all_projects...') const result = await invoke('get_all_projects', { })
const result = await invoke('get_all_projects') return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<Project[]>
console.log('Raw result from Tauri:', result)
// 如果result是字符串尝试解析JSON
if (typeof result === 'string') {
try {
const parsed = JSON.parse(result)
console.log('Parsed result:', parsed)
return parsed as ApiResponse<Project[]>
} catch (parseError) {
console.error('Failed to parse JSON response:', parseError)
return {
status: false,
msg: `Invalid JSON response: ${result}`
}
}
}
return result as ApiResponse<Project[]>
} catch (error) { } catch (error) {
console.error('Failed to get all projects:', error)
return { return {
status: false, status: false,
msg: error instanceof Error ? error.message : 'Unknown error' msg: error instanceof Error ? error.message : 'Unknown error'
@ -72,22 +53,8 @@ export class ProjectService {
static async getProjectById(projectId: string): Promise<ApiResponse<Project>> { static async getProjectById(projectId: string): Promise<ApiResponse<Project>> {
try { try {
const result = await invoke('get_project_by_id', { projectId }) const result = await invoke('get_project_by_id', { projectId })
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<Project>
if (typeof result === 'string') {
try {
const parsed = JSON.parse(result)
return parsed as ApiResponse<Project>
} catch (parseError) {
return {
status: false,
msg: `Invalid JSON response: ${result}`
}
}
}
return result as ApiResponse<Project>
} catch (error) { } catch (error) {
console.error('Failed to get project by id:', error)
return { return {
status: false, status: false,
msg: error instanceof Error ? error.message : 'Unknown error' msg: error instanceof Error ? error.message : 'Unknown error'
@ -100,27 +67,9 @@ export class ProjectService {
*/ */
static async createProject(request: CreateProjectRequest): Promise<ApiResponse<Project>> { static async createProject(request: CreateProjectRequest): Promise<ApiResponse<Project>> {
try { try {
console.log('Calling create_project with:', request)
const result = await invoke('create_project', { request }) const result = await invoke('create_project', { request })
console.log('Raw result from Tauri:', result) return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<Project>
if (typeof result === 'string') {
try {
const parsed = JSON.parse(result)
console.log('Parsed result:', parsed)
return parsed as ApiResponse<Project>
} catch (parseError) {
console.error('Failed to parse JSON response:', parseError)
return {
status: false,
msg: `Invalid JSON response: ${result}`
}
}
}
return result as ApiResponse<Project>
} catch (error) { } catch (error) {
console.error('Failed to create project:', error)
return { return {
status: false, status: false,
msg: error instanceof Error ? error.message : 'Unknown error' msg: error instanceof Error ? error.message : 'Unknown error'
@ -132,27 +81,13 @@ export class ProjectService {
* *
*/ */
static async updateProject( static async updateProject(
projectId: string, projectId: string,
request: UpdateProjectRequest request: UpdateProjectRequest
): Promise<ApiResponse<Project>> { ): Promise<ApiResponse<Project>> {
try { try {
const result = await invoke('update_project', { projectId, request }) const result = await invoke('update_project', { projectId, request })
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<Project>
if (typeof result === 'string') {
try {
const parsed = JSON.parse(result)
return parsed as ApiResponse<Project>
} catch (parseError) {
return {
status: false,
msg: `Invalid JSON response: ${result}`
}
}
}
return result as ApiResponse<Project>
} catch (error) { } catch (error) {
console.error('Failed to update project:', error)
return { return {
status: false, status: false,
msg: error instanceof Error ? error.message : 'Unknown error' msg: error instanceof Error ? error.message : 'Unknown error'
@ -165,23 +100,9 @@ export class ProjectService {
*/ */
static async deleteProject(projectId: string): Promise<ApiResponse<boolean>> { static async deleteProject(projectId: string): Promise<ApiResponse<boolean>> {
try { try {
const result = await invoke('delete_project', { projectId }) const result = await invoke('search_projects', { projectId })
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<boolean>
if (typeof result === 'string') {
try {
const parsed = JSON.parse(result)
return parsed as ApiResponse<boolean>
} catch (parseError) {
return {
status: false,
msg: `Invalid JSON response: ${result}`
}
}
}
return result as ApiResponse<boolean>
} catch (error) { } catch (error) {
console.error('Failed to delete project:', error)
return { return {
status: false, status: false,
msg: error instanceof Error ? error.message : 'Unknown error' msg: error instanceof Error ? error.message : 'Unknown error'
@ -195,22 +116,8 @@ export class ProjectService {
static async searchProjects(keyword: string): Promise<ApiResponse<Project[]>> { static async searchProjects(keyword: string): Promise<ApiResponse<Project[]>> {
try { try {
const result = await invoke('search_projects', { keyword }) const result = await invoke('search_projects', { keyword })
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<Project[]>
if (typeof result === 'string') {
try {
const parsed = JSON.parse(result)
return parsed as ApiResponse<Project[]>
} catch (parseError) {
return {
status: false,
msg: `Invalid JSON response: ${result}`
}
}
}
return result as ApiResponse<Project[]>
} catch (error) { } catch (error) {
console.error('Failed to search projects:', error)
return { return {
status: false, status: false,
msg: error instanceof Error ? error.message : 'Unknown error' msg: error instanceof Error ? error.message : 'Unknown error'
@ -224,26 +131,23 @@ export class ProjectService {
static async openProjectDirectory(projectId: string): Promise<ApiResponse<boolean>> { static async openProjectDirectory(projectId: string): Promise<ApiResponse<boolean>> {
try { try {
const result = await invoke('open_project_directory', { projectId }) const result = await invoke('open_project_directory', { projectId })
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<boolean>
if (typeof result === 'string') {
try {
const parsed = JSON.parse(result)
return parsed as ApiResponse<boolean>
} catch (parseError) {
return {
status: false,
msg: `Invalid JSON response: ${result}`
}
}
}
return result as ApiResponse<boolean>
} catch (error) { } catch (error) {
console.error('Failed to open project directory:', error)
return { return {
status: false, status: false,
msg: error instanceof Error ? error.message : 'Unknown error' msg: error instanceof Error ? error.message : 'Unknown error'
} }
} }
} }
static tryJsonParse(str: any) {
try {
if (typeof str === 'string') {
return JSON.parse(str)
}
return str;
} catch (e) {
return str;
}
}
} }