diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js
index 0673fdf..3803094 100644
--- a/frontend/src/router/index.js
+++ b/frontend/src/router/index.js
@@ -18,6 +18,7 @@ const routes = [
{ path: 'users', name: 'users', component: () => import('@/views/UserManage.vue'), meta: { admin: true } },
{ path: 'factories', name: 'factories', component: () => import('@/views/FactoryManage.vue') },
{ path: 'factories/:id', name: 'factory-detail', component: () => import('@/views/FactoryDetail.vue') },
+ { path: 'brands', name: 'brands', component: () => import('@/views/BrandManage.vue'), meta: { admin: true } },
{ path: 'dictionary', name: 'dictionary', component: () => import('@/views/DictionaryManage.vue'), meta: { admin: true } },
{ path: 'materials', name: 'materials', component: () => import('@/views/MaterialManage.vue') },
{ path: 'materials/:id', name: 'material-detail', component: () => import('@/views/MaterialDetail.vue') }
diff --git a/frontend/src/views/BrandManage.vue b/frontend/src/views/BrandManage.vue
new file mode 100644
index 0000000..5940993
--- /dev/null
+++ b/frontend/src/views/BrandManage.vue
@@ -0,0 +1,210 @@
+
+
+
品牌库
+
+
+ 搜索
+ 新增品牌
+
+
+
+
+
+
+
+
+ {{ formatDate(scope.row.created_at) }}
+
+
+
+
+
+ 编辑
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 取消
+ 保存
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/FactoryDetail.vue b/frontend/src/views/FactoryDetail.vue
index 9579f70..089c96d 100644
--- a/frontend/src/views/FactoryDetail.vue
+++ b/frontend/src/views/FactoryDetail.vue
@@ -7,7 +7,7 @@
{{ displayText(factory.factory_name) }}
- {{ displayText(factory.brand) }}
+ {{ displayText(factory.short_name) }}
{{ displayText(factory.dealer_name) }}
{{ displayText(factory.product_category) }}
{{ displayRegion(factory) }}
diff --git a/frontend/src/views/FactoryManage.vue b/frontend/src/views/FactoryManage.vue
index 3b5d472..0a8f025 100644
--- a/frontend/src/views/FactoryManage.vue
+++ b/frontend/src/views/FactoryManage.vue
@@ -6,7 +6,7 @@
-
+
@@ -52,8 +52,8 @@
-
-
+
+
{
form.dealer_name = ''
form.product_category = ''
form.factory_name = ''
- form.brand = ''
+ form.short_name = ''
form.province = ''
form.city = ''
form.district = ''
diff --git a/frontend/src/views/MaterialDetail.vue b/frontend/src/views/MaterialDetail.vue
index b33f0fb..4ebecef 100644
--- a/frontend/src/views/MaterialDetail.vue
+++ b/frontend/src/views/MaterialDetail.vue
@@ -28,6 +28,7 @@
{{ displayText(material.cost_desc) }}
{{ displayText(material.cases) }}
{{ displayText(material.factory_name) }}
+ {{ displayText(material.brand_name) }}
{{ formatStarLevel(material.quality_level) }}
{{ formatStarLevel(material.durability_level) }}
{{ formatStarLevel(material.eco_level) }}
diff --git a/frontend/src/views/MaterialManage.vue b/frontend/src/views/MaterialManage.vue
index d28c572..23630cc 100644
--- a/frontend/src/views/MaterialManage.vue
+++ b/frontend/src/views/MaterialManage.vue
@@ -9,6 +9,18 @@
+
+
+
查询
{{ importing ? '导入中...' : '导入数据' }}
@@ -32,7 +44,8 @@
-
+
+
@@ -191,7 +204,19 @@
-
+
+
+
+
+
+
@@ -230,6 +255,7 @@ import { useAuth } from '@/store/auth'
import { fetchMaterials, fetchMaterialDetail, createMaterial, updateMaterial, deleteMaterial, submitMaterial, approveMaterial, rejectMaterial, fetchMaterialChoices, uploadImage, importMaterialsExcel, exportMaterialsExcel } from '@/api/material'
import { fetchCategories, fetchSubcategories } from '@/api/category'
import { fetchFactorySimple } from '@/api/factory'
+import { fetchBrands } from '@/api/brand'
const router = useRouter()
const { isAdmin } = useAuth()
@@ -255,9 +281,15 @@ const templateDownloadUrl = `http://101.42.1.64:2260/media/material_import_templ
const filters = reactive({
name: '',
status: '',
- material_subcategory: ''
+ material_subcategory: '',
+ brand: ''
})
+const brandFilterOptions = ref([])
+const brandFormOptions = ref([])
+const brandSearchLoading = ref(false)
+const brandFormSearchLoading = ref(false)
+
const form = reactive({
name: '',
major_category: '',
@@ -290,7 +322,8 @@ const form = reactive({
connection_method: '',
construction_method: '',
limit_condition: '',
- factory: null
+ factory: null,
+ brand: null
})
const majorOptions = ref([])
@@ -392,10 +425,43 @@ const resetForm = () => {
connection_method: '',
construction_method: '',
limit_condition: '',
- factory: null
+ factory: null,
+ brand: null
})
}
+const loadBrandFilterOptions = async () => {
+ const data = await fetchBrands({ page_size: 100 })
+ brandFilterOptions.value = data.results || data
+}
+
+const searchBrands = async (query) => {
+ brandSearchLoading.value = true
+ try {
+ const data = await fetchBrands({ page_size: 50, search: query || '' })
+ brandFilterOptions.value = data.results || data
+ } finally {
+ brandSearchLoading.value = false
+ }
+}
+
+const searchBrandsForForm = async (query) => {
+ brandFormSearchLoading.value = true
+ try {
+ const data = await fetchBrands({ page_size: 50, search: query || '' })
+ brandFormOptions.value = data.results || data
+ } finally {
+ brandFormSearchLoading.value = false
+ }
+}
+
+const ensureBrandInFormOptions = (brandId, brandName) => {
+ if (!brandId) return
+ if (!brandFormOptions.value.some((item) => item.id === brandId)) {
+ brandFormOptions.value = [{ id: brandId, name: brandName || '' }, ...brandFormOptions.value]
+ }
+}
+
const onCategoryChange = async (val, resetSub = true) => {
if (!val) {
await loadSubcategories()
@@ -410,10 +476,11 @@ const onCategoryChange = async (val, resetSub = true) => {
}
}
-const openCreate = () => {
+const openCreate = async () => {
resetForm()
isEdit.value = false
dialogTitle.value = '新增材料'
+ await searchBrandsForForm('')
dialogVisible.value = true
}
@@ -426,9 +493,12 @@ const openEdit = async (row) => {
form.application_scene = item.application_scene || []
form.advantage = item.advantage || []
form.brochure_url = item.brochure_url || ''
+ form.brand = item.brand || null
if (form.material_category) {
await onCategoryChange(form.material_category, false)
}
+ await searchBrandsForForm('')
+ ensureBrandInFormOptions(item.brand, item.brand_name)
dialogTitle.value = '编辑材料'
dialogVisible.value = true
}
@@ -448,9 +518,14 @@ const handleUpload = async (options) => {
}
const onSave = async () => {
+ if (!form.brand) {
+ ElMessage.warning('请选择品牌')
+ return
+ }
try {
const payload = { ...form }
delete payload.brochure_url
+ delete payload.brand_name
if (!isAdmin.value) {
delete payload.factory
}
@@ -580,6 +655,7 @@ onMounted(() => {
loadCategories()
loadSubcategories()
loadFactories()
+ loadBrandFilterOptions()
loadMaterials()
})