Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
Z
zxn-adputin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lijin
zxn-adputin
Commits
83007dea
Commit
83007dea
authored
Mar 05, 2025
by
lijin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
增加素材组管理功能
parent
2b9434c0
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
829 additions
and
1 deletion
+829
-1
materialGroup.js
src/api/materialGroup.js
+43
-0
index.vue
src/components/TagTransfer/index.vue
+327
-0
index.js
src/router/index.js
+6
-0
Layout.vue
src/views/layout/Layout.vue
+1
-1
index.vue
src/views/materialGroup/index.vue
+452
-0
No files found.
src/api/materialGroup.js
0 → 100644
View file @
83007dea
import
request
from
'@/utils/request'
// 获取所有素材组
export
function
getAllMaterialGroups
()
{
return
request
({
url
:
`
${
process
.
env
.
PUTIN_API
}
/material-groups`
,
method
:
'get'
})
}
// 根据ID获取素材组
export
function
getMaterialGroupById
(
id
)
{
return
request
({
url
:
`
${
process
.
env
.
PUTIN_API
}
/material-groups/
${
id
}
`
,
method
:
'get'
})
}
// 创建素材组
export
function
createMaterialGroup
(
data
)
{
return
request
({
url
:
`
${
process
.
env
.
PUTIN_API
}
/material-groups`
,
method
:
'post'
,
data
})
}
// 更新素材组
export
function
updateMaterialGroup
(
id
,
data
)
{
return
request
({
url
:
`
${
process
.
env
.
PUTIN_API
}
/material-groups/
${
id
}
`
,
method
:
'put'
,
data
})
}
// 删除素材组
export
function
deleteMaterialGroup
(
id
)
{
return
request
({
url
:
`
${
process
.
env
.
PUTIN_API
}
/material-groups/
${
id
}
`
,
method
:
'delete'
})
}
src/components/TagTransfer/index.vue
0 → 100644
View file @
83007dea
<
template
>
<div
class=
"tag-transfer-container"
>
<el-row
:gutter=
"20"
>
<!-- 左侧树形结构 -->
<el-col
:span=
"10"
>
<el-card
class=
"tree-card"
>
<div
slot=
"header"
class=
"card-header"
>
<span>
可选标签
</span>
<div
class=
"search-input"
>
<el-input
v-model=
"searchQuery"
placeholder=
"搜索标签"
prefix-icon=
"el-icon-search"
clearable
@
input=
"filterTree"
></el-input>
</div>
</div>
<!-- 使用v-if强制重新渲染树组件 -->
<el-tree
v-if=
"treeKey"
ref=
"tree"
:key=
"treeKey"
:data=
"treeData"
:props=
"defaultProps"
node-key=
"id"
show-checkbox
:filter-node-method=
"filterNode"
:default-checked-keys=
"selectedKeys"
@
check=
"handleCheck"
>
</el-tree>
</el-card>
</el-col>
<!-- 右侧已选标签 -->
<el-col
:span=
"10"
>
<el-card
class=
"selected-card"
>
<div
slot=
"header"
class=
"card-header"
>
<span>
已选标签
</span>
<el-button
type=
"text"
@
click=
"clearSelected"
>
清空
</el-button>
</div>
<div
class=
"selected-tags"
v-if=
"selectedTags.length > 0"
>
<el-tag
v-for=
"tag in selectedTags"
:key=
"tag.id"
closable
@
close=
"removeTag(tag.id)"
class=
"tag-item"
>
{{
getTagPath
(
tag
)
}}
</el-tag>
</div>
<div
v-else
class=
"no-data"
>
暂无选中标签
</div>
</el-card>
</el-col>
</el-row>
</div>
</
template
>
<
script
>
import
{
getAllMaterialTags
}
from
'@/api/materialTag'
export
default
{
name
:
'TagTransfer'
,
props
:
{
value
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
// 强制组件重新渲染
beforeUpdate
()
{
console
.
log
(
'TagTransfer beforeUpdate, value:'
,
this
.
value
)
},
// 添加updated钩子检测值变化
updated
()
{
console
.
log
(
'TagTransfer updated, value:'
,
this
.
value
,
'selectedKeys:'
,
this
.
selectedKeys
)
},
data
()
{
return
{
allTags
:
[],
searchQuery
:
''
,
defaultProps
:
{
children
:
'children'
,
label
:
'name'
},
selectedKeys
:
[],
tagsMap
:
{},
treeKey
:
1
// 树组件的key,用于强制重新渲染
}
},
computed
:
{
treeData
()
{
return
this
.
buildTreeData
()
},
selectedTags
()
{
return
this
.
selectedKeys
.
map
(
id
=>
this
.
tagsMap
[
id
]).
filter
(
Boolean
)
}
},
watch
:
{
value
:
{
immediate
:
true
,
deep
:
true
,
handler
(
newVal
)
{
console
.
log
(
'TagTransfer value changed:'
,
newVal
)
if
(
!
Array
.
isArray
(
newVal
))
{
console
.
warn
(
'TagTransfer received non-array value:'
,
newVal
)
this
.
selectedKeys
=
[]
}
else
{
// 使用JSON序列化确保引用断开
this
.
selectedKeys
=
JSON
.
parse
(
JSON
.
stringify
(
newVal
))
}
// 增加treeKey强制树组件重新渲染
this
.
treeKey
++
console
.
log
(
'强制重新渲染树组件, treeKey:'
,
this
.
treeKey
)
// 等待树组件重新渲染后再设置选中状态
this
.
$nextTick
(()
=>
{
if
(
this
.
$refs
.
tree
)
{
console
.
log
(
'Setting checked keys in watcher:'
,
this
.
selectedKeys
)
this
.
$refs
.
tree
.
setCheckedKeys
(
this
.
selectedKeys
)
}
})
}
}
},
created
()
{
this
.
fetchTags
()
},
// 组件更新时的生命周期钩子
updated
()
{
console
.
log
(
'TagTransfer updated, selectedKeys:'
,
this
.
selectedKeys
)
},
methods
:
{
// 获取标签数据
fetchTags
()
{
getAllMaterialTags
().
then
(
response
=>
{
if
(
response
.
status
===
200
&&
response
.
result
&&
response
.
result
.
data
)
{
this
.
allTags
=
response
.
result
.
data
// 创建标签映射关系
this
.
tagsMap
=
{}
this
.
allTags
.
forEach
(
tag
=>
{
this
.
tagsMap
[
tag
.
id
]
=
tag
})
// 增加treeKey强制树组件重新渲染
this
.
treeKey
++
console
.
log
(
'标签加载完成,强制重新渲染树组件, treeKey:'
,
this
.
treeKey
)
// 等待树组件重新渲染后再设置选中状态
this
.
$nextTick
(()
=>
{
if
(
this
.
$refs
.
tree
)
{
console
.
log
(
'设置选中标签:'
,
this
.
selectedKeys
)
this
.
$refs
.
tree
.
setCheckedKeys
(
this
.
selectedKeys
)
}
})
}
}).
catch
(
error
=>
{
console
.
error
(
'获取标签失败:'
,
error
)
this
.
$message
.
error
(
'获取标签失败'
)
})
},
// 构建树形数据
buildTreeData
()
{
// 根据父子关系构建树
const
rootNodes
=
this
.
allTags
.
filter
(
tag
=>
!
tag
.
parentId
)
return
this
.
buildTree
(
rootNodes
)
},
// 递归构建树
buildTree
(
nodes
)
{
return
nodes
.
map
(
node
=>
{
const
children
=
this
.
allTags
.
filter
(
tag
=>
tag
.
parentId
===
node
.
id
)
const
treeNode
=
{
id
:
node
.
id
,
name
:
node
.
name
,
parentId
:
node
.
parentId
}
if
(
children
.
length
>
0
)
{
treeNode
.
children
=
this
.
buildTree
(
children
)
}
return
treeNode
})
},
// 过滤节点
filterNode
(
value
,
data
)
{
if
(
!
value
)
return
true
return
data
.
name
.
toLowerCase
().
includes
(
value
.
toLowerCase
())
},
// 过滤树
filterTree
()
{
this
.
$refs
.
tree
.
filter
(
this
.
searchQuery
)
},
// 处理选中变化
handleCheck
(
data
,
checked
)
{
console
.
log
(
'树选中变化:'
,
checked
)
// 使用JSON序列化确保断开引用
this
.
selectedKeys
=
JSON
.
parse
(
JSON
.
stringify
(
checked
.
checkedKeys
))
// 使用setTimeout确保在当前事件循环结束后触发事件
setTimeout
(()
=>
{
this
.
$emit
(
'input'
,
this
.
selectedKeys
)
this
.
$emit
(
'change'
,
this
.
selectedKeys
)
},
0
)
},
// 移除标签
removeTag
(
tagId
)
{
this
.
selectedKeys
=
this
.
selectedKeys
.
filter
(
id
=>
id
!==
tagId
)
// 增加treeKey强制树组件重新渲染
this
.
treeKey
++
// 等待树组件重新渲染后再设置选中状态
this
.
$nextTick
(()
=>
{
if
(
this
.
$refs
.
tree
)
{
this
.
$refs
.
tree
.
setCheckedKeys
(
this
.
selectedKeys
)
}
// 使用setTimeout确保在当前事件循环结束后触发事件
setTimeout
(()
=>
{
const
selectedKeysToEmit
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
selectedKeys
))
this
.
$emit
(
'input'
,
selectedKeysToEmit
)
this
.
$emit
(
'change'
,
selectedKeysToEmit
)
},
0
)
})
},
// 清空选中
clearSelected
()
{
this
.
selectedKeys
=
[]
// 增加treeKey强制树组件重新渲染
this
.
treeKey
++
// 等待树组件重新渲染后再设置选中状态
this
.
$nextTick
(()
=>
{
if
(
this
.
$refs
.
tree
)
{
this
.
$refs
.
tree
.
setCheckedKeys
([])
}
// 使用setTimeout确保在当前事件循环结束后触发事件
setTimeout
(()
=>
{
this
.
$emit
(
'input'
,
[])
this
.
$emit
(
'change'
,
[])
},
0
)
})
},
// 获取标签路径
getTagPath
(
tag
)
{
if
(
!
tag
)
return
''
const
path
=
[]
let
currentTag
=
tag
while
(
currentTag
)
{
path
.
unshift
(
currentTag
.
name
)
if
(
currentTag
.
parentId
)
{
currentTag
=
this
.
tagsMap
[
currentTag
.
parentId
]
}
else
{
break
}
}
return
path
.
join
(
' / '
)
}
}
}
</
script
>
<
style
scoped
>
.tag-transfer-container
{
margin-bottom
:
20px
;
}
.card-header
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
}
.search-input
{
width
:
150px
;
}
.tree-card
,
.selected-card
{
height
:
400px
;
overflow-y
:
auto
;
}
.selected-tags
{
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
8px
;
}
.tag-item
{
margin-right
:
8px
;
margin-bottom
:
8px
;
}
.no-data
{
color
:
#909399
;
text-align
:
center
;
margin-top
:
20px
;
}
</
style
>
src/router/index.js
View file @
83007dea
...
...
@@ -156,6 +156,12 @@ export const constantRouterMap = [
component
:
()
=>
import
(
'@/views/materialTag'
),
meta
:
{
title
:
'标签管理'
}
},
{
path
:
'/assetManagement/material-group'
,
name
:
'assetManagement.material-group'
,
component
:
()
=>
import
(
'@/views/materialGroup'
),
meta
:
{
title
:
'素材组管理'
}
},
]
},
...
...
src/views/layout/Layout.vue
View file @
83007dea
...
...
@@ -26,10 +26,10 @@
<!-- 带子菜单的导航项 -->
<el-submenu
index=
"4"
>
<
template
slot=
"title"
>
资产管理
</
template
>
<el-menu-item
index=
"/assetManagement/material-group"
>
素材组管理
</el-menu-item>
<el-menu-item
index=
"/assetManagement/copywritingLibrary"
>
文案管理
</el-menu-item>
<el-menu-item
index=
"/assetManagement/app-group"
>
产品组管理
</el-menu-item>
<el-menu-item
index=
"/assetManagement/location-group"
>
地域组管理
</el-menu-item>
<el-menu-item
index=
"/assetManagement/createDelivery"
>
素材组
</el-menu-item>
<el-menu-item
index=
"/assetManagement/title-group"
>
标题组管理
</el-menu-item>
<el-menu-item
index=
"/assetManagement/description-group"
>
描述组管理
</el-menu-item>
<el-menu-item
index=
"/assetManagement/material-tag"
>
标签管理
</el-menu-item>
...
...
src/views/materialGroup/index.vue
0 → 100644
View file @
83007dea
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment