fix
This commit is contained in:
parent
a9b411bc41
commit
d6dd6109c0
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useState, useEffect } from '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'
|
||||
|
||||
const ProjectManagePage: React.FC = () => {
|
||||
|
|
@ -100,9 +101,13 @@ const ProjectManagePage: React.FC = () => {
|
|||
|
||||
const selectDirectory = async () => {
|
||||
try {
|
||||
// TODO: 使用Tauri的文件选择器
|
||||
const directory = prompt('请输入项目目录路径:')
|
||||
if (directory) {
|
||||
const directory = await open({
|
||||
directory: true,
|
||||
multiple: false,
|
||||
title: '选择项目目录'
|
||||
})
|
||||
|
||||
if (directory && typeof directory === 'string') {
|
||||
setFormData({ ...formData, local_directory: directory })
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -112,9 +117,18 @@ const ProjectManagePage: React.FC = () => {
|
|||
|
||||
const selectImage = async () => {
|
||||
try {
|
||||
// TODO: 使用Tauri的文件选择器
|
||||
const imagePath = prompt('请输入商品图片路径:')
|
||||
if (imagePath) {
|
||||
const imagePath = await open({
|
||||
multiple: false,
|
||||
title: '选择商品图片',
|
||||
filters: [
|
||||
{
|
||||
name: '图片文件',
|
||||
extensions: ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp', 'svg']
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
if (imagePath && typeof imagePath === 'string') {
|
||||
setFormData({ ...formData, product_image: imagePath })
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -319,14 +333,17 @@ const ProjectManagePage: React.FC = () => {
|
|||
type="text"
|
||||
value={formData.local_directory}
|
||||
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"
|
||||
readOnly
|
||||
/>
|
||||
<button
|
||||
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} />
|
||||
<span className="text-sm">选择</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -355,16 +372,40 @@ const ProjectManagePage: React.FC = () => {
|
|||
type="text"
|
||||
value={formData.product_image}
|
||||
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"
|
||||
readOnly
|
||||
/>
|
||||
<button
|
||||
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} />
|
||||
<span className="text-sm">选择</span>
|
||||
</button>
|
||||
</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>
|
||||
|
||||
|
|
|
|||
|
|
@ -37,28 +37,9 @@ export class ProjectService {
|
|||
*/
|
||||
static async getAllProjects(): Promise<ApiResponse<Project[]>> {
|
||||
try {
|
||||
console.log('Calling get_all_projects...')
|
||||
const result = await invoke('get_all_projects')
|
||||
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[]>
|
||||
const result = await invoke('get_all_projects', { })
|
||||
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<Project[]>
|
||||
} catch (error) {
|
||||
console.error('Failed to get all projects:', error)
|
||||
return {
|
||||
status: false,
|
||||
msg: error instanceof Error ? error.message : 'Unknown error'
|
||||
|
|
@ -72,22 +53,8 @@ export class ProjectService {
|
|||
static async getProjectById(projectId: string): Promise<ApiResponse<Project>> {
|
||||
try {
|
||||
const result = await invoke('get_project_by_id', { projectId })
|
||||
|
||||
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>
|
||||
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<Project>
|
||||
} catch (error) {
|
||||
console.error('Failed to get project by id:', error)
|
||||
return {
|
||||
status: false,
|
||||
msg: error instanceof Error ? error.message : 'Unknown error'
|
||||
|
|
@ -100,27 +67,9 @@ export class ProjectService {
|
|||
*/
|
||||
static async createProject(request: CreateProjectRequest): Promise<ApiResponse<Project>> {
|
||||
try {
|
||||
console.log('Calling create_project with:', request)
|
||||
const result = await invoke('create_project', { request })
|
||||
console.log('Raw result from Tauri:', result)
|
||||
|
||||
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>
|
||||
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<Project>
|
||||
} catch (error) {
|
||||
console.error('Failed to create project:', error)
|
||||
return {
|
||||
status: false,
|
||||
msg: error instanceof Error ? error.message : 'Unknown error'
|
||||
|
|
@ -132,27 +81,13 @@ export class ProjectService {
|
|||
* 更新项目
|
||||
*/
|
||||
static async updateProject(
|
||||
projectId: string,
|
||||
projectId: string,
|
||||
request: UpdateProjectRequest
|
||||
): Promise<ApiResponse<Project>> {
|
||||
try {
|
||||
const result = await invoke('update_project', { projectId, request })
|
||||
|
||||
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>
|
||||
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<Project>
|
||||
} catch (error) {
|
||||
console.error('Failed to update project:', error)
|
||||
return {
|
||||
status: false,
|
||||
msg: error instanceof Error ? error.message : 'Unknown error'
|
||||
|
|
@ -165,23 +100,9 @@ export class ProjectService {
|
|||
*/
|
||||
static async deleteProject(projectId: string): Promise<ApiResponse<boolean>> {
|
||||
try {
|
||||
const result = await invoke('delete_project', { projectId })
|
||||
|
||||
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>
|
||||
const result = await invoke('search_projects', { projectId })
|
||||
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<boolean>
|
||||
} catch (error) {
|
||||
console.error('Failed to delete project:', error)
|
||||
return {
|
||||
status: false,
|
||||
msg: error instanceof Error ? error.message : 'Unknown error'
|
||||
|
|
@ -195,22 +116,8 @@ export class ProjectService {
|
|||
static async searchProjects(keyword: string): Promise<ApiResponse<Project[]>> {
|
||||
try {
|
||||
const result = await invoke('search_projects', { keyword })
|
||||
|
||||
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[]>
|
||||
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<Project[]>
|
||||
} catch (error) {
|
||||
console.error('Failed to search projects:', error)
|
||||
return {
|
||||
status: false,
|
||||
msg: error instanceof Error ? error.message : 'Unknown error'
|
||||
|
|
@ -224,26 +131,23 @@ export class ProjectService {
|
|||
static async openProjectDirectory(projectId: string): Promise<ApiResponse<boolean>> {
|
||||
try {
|
||||
const result = await invoke('open_project_directory', { projectId })
|
||||
|
||||
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>
|
||||
return { status: true, msg: 'ok', data: this.tryJsonParse(result) } as ApiResponse<boolean>
|
||||
} catch (error) {
|
||||
console.error('Failed to open project directory:', error)
|
||||
return {
|
||||
status: false,
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue