fix
This commit is contained in:
parent
a9b411bc41
commit
d6dd6109c0
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue