提交所有内容

This commit is contained in:
super
2026-03-22 12:45:58 +08:00
parent c5d62c71a3
commit 5b636c3dfd
44 changed files with 85 additions and 295 deletions

Binary file not shown.

Binary file not shown.

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

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

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

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

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

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

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

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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -57,6 +57,17 @@ def _push_task_event(task_id, event):
def _expand_folder_xlsx(folder_path): def _expand_folder_xlsx(folder_path):
"""返回文件夹下第一层 .xlsx 文件的绝对路径列表(保留旧逻辑,不再用于品牌工具文件夹上传)"""
if not folder_path or not os.path.isdir(folder_path):
return []
paths = []
for name in os.listdir(folder_path):
if name.endswith('.xlsx') or name.endswith('.XLSX'):
paths.append(os.path.normpath(os.path.join(folder_path, name)))
return paths
def _expand_folder_xlsx_recursive_items(folder_path):
"""返回文件夹下所有 .xlsx 文件的绝对路径和相对路径列表(递归)""" """返回文件夹下所有 .xlsx 文件的绝对路径和相对路径列表(递归)"""
if not folder_path or not os.path.isdir(folder_path): if not folder_path or not os.path.isdir(folder_path):
return [] return []
@@ -487,7 +498,22 @@ def api_brand_expand_folder():
folder = (data.get('folder') or '').strip() folder = (data.get('folder') or '').strip()
if not folder: if not folder:
return jsonify({'success': False, 'error': '请提供 folder 路径'}), 400 return jsonify({'success': False, 'error': '请提供 folder 路径'}), 400
items = _expand_folder_xlsx(folder) paths = _expand_folder_xlsx(folder)
return jsonify({'success': True, 'paths': paths})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@brand_bp.route('/api/brand/expand-folder-recursive', methods=['POST'])
@login_required
def api_brand_expand_folder_recursive():
"""递归展开文件夹,返回 .xlsx 文件绝对路径及相对路径列表"""
try:
data = request.get_json() or {}
folder = (data.get('folder') or '').strip()
if not folder:
return jsonify({'success': False, 'error': '请提供 folder 路径'}), 400
items = _expand_folder_xlsx_recursive_items(folder)
return jsonify({'success': True, 'items': items}) return jsonify({'success': True, 'items': items})
except Exception as e: except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500 return jsonify({'success': False, 'error': str(e)}), 500

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -211,7 +211,7 @@ class WindowAPI:
except Exception as e: except Exception as e:
return {'success': False, 'error': str(e)} return {'success': False, 'error': str(e)}
def upload_file_to_java(self, file_path): def upload_file_to_java(self, file_path, relative_path=None):
"""按本地路径读取文件并上传到 Java 后端临时目录。""" """按本地路径读取文件并上传到 Java 后端临时目录。"""
if not file_path or not str(file_path).strip(): if not file_path or not str(file_path).strip():
return {'success': False, 'error': '文件路径为空'} return {'success': False, 'error': '文件路径为空'}
@@ -223,6 +223,7 @@ class WindowAPI:
response = requests.post( response = requests.post(
f"{JAVA_API_BASE}/api/files/upload", f"{JAVA_API_BASE}/api/files/upload",
files={'file': (os.path.basename(normalized_path), file_obj)}, files={'file': (os.path.basename(normalized_path), file_obj)},
data={'relativePath': str(relative_path).strip()} if relative_path else None,
timeout=120, timeout=120,
) )
response.raise_for_status() response.raise_for_status()

View File

@@ -1,18 +1,15 @@
<!doctype html> <!doctype html>
<html lang="zh-CN"> <html lang="zh-CN">
<head>
<head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>格式转换 - 数富AI</title> <title>格式转换 - 数富AI</title>
<script type="module" crossorigin src="/assets/convert.js"></script> <script type="module" crossorigin src="/assets/convert.js"></script>
<link rel="modulepreload" crossorigin href="/assets/pywebview-BnpJyyGZ.js"> <link rel="modulepreload" crossorigin href="/assets/pywebview-BRrok0pS.js">
<link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css"> <link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css">
<link rel="stylesheet" crossorigin href="/assets/convert-BxkpMHO9.css"> <link rel="stylesheet" crossorigin href="/assets/convert-Cfr3mUjs.css">
</head> </head>
<body>
<body>
<div id="app"></div> <div id="app"></div>
</body> </body>
</html> </html>

View File

@@ -1,18 +1,15 @@
<!doctype html> <!doctype html>
<html lang="zh-CN"> <html lang="zh-CN">
<head>
<head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>数据去重 - 数富AI</title> <title>数据去重 - 数富AI</title>
<script type="module" crossorigin src="/assets/dedupe.js"></script> <script type="module" crossorigin src="/assets/dedupe.js"></script>
<link rel="modulepreload" crossorigin href="/assets/pywebview-BnpJyyGZ.js"> <link rel="modulepreload" crossorigin href="/assets/pywebview-BRrok0pS.js">
<link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css"> <link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css">
<link rel="stylesheet" crossorigin href="/assets/dedupe-DzFvTfoj.css"> <link rel="stylesheet" crossorigin href="/assets/dedupe-CS18ls2z.css">
</head> </head>
<body>
<body>
<div id="app"></div> <div id="app"></div>
</body> </body>
</html> </html>

View File

@@ -1,18 +1,15 @@
<!doctype html> <!doctype html>
<html lang="zh-CN"> <html lang="zh-CN">
<head>
<head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>数据拆分 - 数富AI</title> <title>数据拆分 - 数富AI</title>
<script type="module" crossorigin src="/assets/split.js"></script> <script type="module" crossorigin src="/assets/split.js"></script>
<link rel="modulepreload" crossorigin href="/assets/pywebview-BnpJyyGZ.js"> <link rel="modulepreload" crossorigin href="/assets/pywebview-BRrok0pS.js">
<link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css"> <link rel="stylesheet" crossorigin href="/assets/pywebview-IqgMfeBe.css">
<link rel="stylesheet" crossorigin href="/assets/split-DidKJ84l.css"> <link rel="stylesheet" crossorigin href="/assets/split-mwLUJT1K.css">
</head> </head>
<body>
<body>
<div id="app"></div> <div id="app"></div>
</body> </body>
</html> </html>

View File

@@ -173,7 +173,7 @@
import { computed, onMounted, ref } from 'vue' import { computed, onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import BrandTopBar from './BrandTopBar.vue' import BrandTopBar from './BrandTopBar.vue'
import { expandBrandFolder, getBrandTemplateXlsxUrl, getBrandTemplateZipUrl } from '@/shared/api/brand' import { expandBrandFolderRecursive, getBrandTemplateXlsxUrl, getBrandTemplateZipUrl } from '@/shared/api/brand'
import type { BrandExpandFolderItem } from '@/shared/api/brand' import type { BrandExpandFolderItem } from '@/shared/api/brand'
import { import {
deleteConvertHistory, deleteConvertHistory,
@@ -288,7 +288,7 @@ async function selectConvertFolder() {
if (!folder) return if (!folder) return
convertArchiveName.value = folder.split(/[/\\]/).filter(Boolean).pop() || '' convertArchiveName.value = folder.split(/[/\\]/).filter(Boolean).pop() || ''
const result = await expandBrandFolder(folder) const result = await expandBrandFolderRecursive(folder)
if (result.success && result.items?.length) { if (result.success && result.items?.length) {
convertSelectedPaths.value = result.items.map((item) => item.relativePath) convertSelectedPaths.value = result.items.map((item) => item.relativePath)
convertUploadedFiles.value = await uploadPathsToJava(result.items) convertUploadedFiles.value = await uploadPathsToJava(result.items)

View File

@@ -147,7 +147,7 @@
import { computed, onMounted, ref } from 'vue' import { computed, onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import BrandTopBar from './BrandTopBar.vue' import BrandTopBar from './BrandTopBar.vue'
import { expandBrandFolder, type BrandExpandFolderItem } from '@/shared/api/brand' import { expandBrandFolderRecursive, type BrandExpandFolderItem } from '@/shared/api/brand'
import { deleteDedupeHistory, getDedupeHistory, getExcelInfo, runDedupe, type DedupeResultItem, type DedupeRunVo } from '@/shared/api/java-modules' import { deleteDedupeHistory, getDedupeHistory, getExcelInfo, runDedupe, type DedupeResultItem, type DedupeRunVo } from '@/shared/api/java-modules'
import { getPywebviewApi, type UploadedJavaFile } from '@/shared/bridges/pywebview' import { getPywebviewApi, type UploadedJavaFile } from '@/shared/bridges/pywebview'
@@ -247,7 +247,7 @@ async function selectCleanFolder() {
if (!folder) return if (!folder) return
cleanArchiveName.value = folder.split(/[/\\]/).filter(Boolean).pop() || '' cleanArchiveName.value = folder.split(/[/\\]/).filter(Boolean).pop() || ''
const result = await expandBrandFolder(folder) const result = await expandBrandFolderRecursive(folder)
if (result.success && result.items?.length) { if (result.success && result.items?.length) {
cleanSelectedPaths.value = result.items.map((item) => item.relativePath) cleanSelectedPaths.value = result.items.map((item) => item.relativePath)
cleanUploadedFiles.value = await uploadPathsToJava(result.items) cleanUploadedFiles.value = await uploadPathsToJava(result.items)

View File

@@ -172,7 +172,7 @@
import { computed, onMounted, ref } from 'vue' import { computed, onMounted, ref } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import BrandTopBar from './BrandTopBar.vue' import BrandTopBar from './BrandTopBar.vue'
import { expandBrandFolder, type BrandExpandFolderItem } from '@/shared/api/brand' import { expandBrandFolderRecursive, type BrandExpandFolderItem } from '@/shared/api/brand'
import { deleteSplitHistory, getExcelInfo, getSplitHistory, runSplit, type SplitResultItem, type SplitRunVo } from '@/shared/api/java-modules' import { deleteSplitHistory, getExcelInfo, getSplitHistory, runSplit, type SplitResultItem, type SplitRunVo } from '@/shared/api/java-modules'
import { getPywebviewApi, type UploadedJavaFile } from '@/shared/bridges/pywebview' import { getPywebviewApi, type UploadedJavaFile } from '@/shared/bridges/pywebview'
@@ -262,7 +262,7 @@ async function selectSplitFolder() {
if (!folder) return if (!folder) return
splitArchiveName.value = folder.split(/[/\\]/).filter(Boolean).pop() || '' splitArchiveName.value = folder.split(/[/\\]/).filter(Boolean).pop() || ''
const result = await expandBrandFolder(folder) const result = await expandBrandFolderRecursive(folder)
if (result.success && result.items?.length) { if (result.success && result.items?.length) {
splitSelectedPaths.value = result.items.map((item) => item.relativePath) splitSelectedPaths.value = result.items.map((item) => item.relativePath)
splitUploadedFiles.value = await uploadPathsToJava(result.items) splitUploadedFiles.value = await uploadPathsToJava(result.items)

View File

@@ -66,6 +66,10 @@ export function expandBrandFolder(folder: string) {
return requestPostJson<BrandExpandFolderResponse>(`${API_PREFIX}/api/brand/expand-folder`, { folder }) return requestPostJson<BrandExpandFolderResponse>(`${API_PREFIX}/api/brand/expand-folder`, { folder })
} }
export function expandBrandFolderRecursive(folder: string) {
return requestPostJson<BrandExpandFolderResponse>(`${API_PREFIX}/api/brand/expand-folder-recursive`, { folder })
}
export function runBrandNow(paths: string[], strategy: string) { export function runBrandNow(paths: string[], strategy: string) {
return requestPostJson<BrandTaskMutationResponse>(`${API_PREFIX}/api/brand/run`, { paths, strategy }) return requestPostJson<BrandTaskMutationResponse>(`${API_PREFIX}/api/brand/run`, { paths, strategy })
} }