feat: add noRecipe flag to items and revamp recipe list

Add noRecipe toggle to item editor to prevent recipe creation
Change RecipeList to display items and their recipe status
Show recipe details and related recipes directly in ItemDetail
This commit is contained in:
2026-04-30 16:52:59 +08:00
parent a7086823ff
commit 45e0276158
7 changed files with 232 additions and 42 deletions

View File

@@ -23,8 +23,13 @@ const recipeForm = ref({
const routeId = computed(() => (typeof route.params.id === 'string' ? route.params.id : ''));
const isEditing = computed(() => routeId.value !== '');
const itemSelectOptions = computed(() => itemRows.value.map((item) => ({ id: item.id, name: item.name })));
const selectedItemName = computed(() => itemSelectOptions.value.find((item) => String(item.id) === recipeForm.value.itemId)?.name ?? '');
const materialItemOptions = computed(() => itemRows.value.map((item) => ({ id: item.id, name: item.name })));
const resultItemOptions = computed(() =>
itemRows.value
.filter((item) => !item.noRecipe || String(item.id) === recipeForm.value.itemId)
.map((item) => ({ id: item.id, name: item.name }))
);
const selectedItemName = computed(() => resultItemOptions.value.find((item) => String(item.id) === recipeForm.value.itemId)?.name ?? '');
const pageTitle = computed(() => (isEditing.value ? `编辑 ${selectedItemName.value || '材料单'}` : '新增材料单'));
const cancelTo = computed(() => (isEditing.value ? `/recipes/${routeId.value}` : '/recipes'));
@@ -42,6 +47,15 @@ function errorText(error: unknown, fallback: string) {
return error instanceof Error && error.message ? error.message : fallback;
}
function preselectedItemId() {
const itemId = route.query.itemId;
if (typeof itemId !== 'string') {
return '';
}
return resultItemOptions.value.some((item) => String(item.id) === itemId) ? itemId : '';
}
async function loadEditor() {
loading.value = true;
message.value = '';
@@ -58,6 +72,8 @@ async function loadEditor() {
acquisitionMethodIds: recipe.acquisition_methods.map((method) => String(method.id)),
materials: recipe.materials.map((material) => ({ itemId: String(material.id), quantity: material.quantity }))
};
} else {
recipeForm.value.itemId = preselectedItemId();
}
} catch (error) {
message.value = errorText(error, '加载失败');
@@ -135,7 +151,7 @@ onMounted(() => {
<TagsSelect
id="recipe-item"
v-model="recipeForm.itemId"
:options="itemSelectOptions"
:options="resultItemOptions"
:multiple="false"
placeholder="请选择"
search-placeholder="搜索物品"
@@ -161,7 +177,7 @@ onMounted(() => {
<TagsSelect
:id="`recipe-material-${index}`"
v-model="row.itemId"
:options="itemSelectOptions"
:options="materialItemOptions"
:multiple="false"
placeholder="请选择"
search-placeholder="搜索物品"