feat:新增修改删除书签功能

This commit is contained in:
CN32479-詹红柱 2021-08-15 00:22:50 +08:00
parent 2c5ba8a454
commit a3d22a8b60
2 changed files with 125 additions and 32 deletions

View File

@ -11,8 +11,7 @@
<img src="./assets/svg/search.svg"> <img src="./assets/svg/search.svg">
<input type="text" placeholder="请输入书签名称" v-model="searchVal" /> <input type="text" placeholder="请输入书签名称" v-model="searchVal" />
</div> </div>
<img src="./assets/svg/add.svg" class="tool-icon" @click="add" /> <img src="./assets/svg/add.svg" class="tool-icon" @click="add({},'add')" />
<a title="我的博客" href="https://zhanhongzhu.top" target="_blank"><img src="./assets/svg/blog.svg" class="tool-icon" /></a> <a title="我的博客" href="https://zhanhongzhu.top" target="_blank"><img src="./assets/svg/blog.svg" class="tool-icon" /></a>
<a title="在线翻译" href="https://translate.google.cn" target="_blank"><img src="./assets/svg/translate.svg" class="tool-icon" /></a> <a title="在线翻译" href="https://translate.google.cn" target="_blank"><img src="./assets/svg/translate.svg" class="tool-icon" /></a>
<a title="我的码云" href="https://gitee.com/zhanhongzhu/kestrel-bookmark" target="_blank"><img src="./assets/svg/gitee.svg" class="tool-icon" /></a> <a title="我的码云" href="https://gitee.com/zhanhongzhu/kestrel-bookmark" target="_blank"><img src="./assets/svg/gitee.svg" class="tool-icon" /></a>
@ -32,8 +31,13 @@
<div class="card-item list-complete-item" v-for="(card,idx) in bookMark" :key="idx" @click="navigate(card)"> <div class="card-item list-complete-item" v-for="(card,idx) in bookMark" :key="idx" @click="navigate(card)">
<div class="logo-img"><img :src="card.logo?card.logo:'/img/logo.f38dc2e8.svg'" /></div> <div class="logo-img"><img :src="card.logo?card.logo:'/img/logo.f38dc2e8.svg'" /></div>
<div class="logo-box"> <div class="logo-box">
<span class="title">{{card.title}}</span> <span class="logo-box-tools">
<span class="subtitle">{{card.desc}}</span> <i class="el-icon-edit" @click.stop="add(card,'modify')"></i>
<i class="el-icon-delete" @click.stop="deleteClick(card)"></i>
</span>
<span class="title">{{card.title || 'Kestrel-bookmark'}}</span>
<span class="subtitle">{{card.desc || "红隼书签-为中国 Web 前端开发人员提供优质网站导航"}}</span>
</div> </div>
</div> </div>
</transition-group> </transition-group>
@ -55,7 +59,7 @@
</div> </div>
</div> </div>
</div> </div>
<Dialog class="my-dialog" v-model="isDetailVisible" @closeViews="closeViews" :selectType="activeIndex" @fresh="search"/> <Dialog class="my-dialog" v-model="isDetailVisible" @closeViews="closeViews" :detail="detail" :selectType="activeIndex" @fresh="search" />
</template> </template>
<script> <script>
@ -64,6 +68,7 @@ import { myData } from './assets/Json/印象笔记.js'
import { watch } from '@vue/runtime-core' import { watch } from '@vue/runtime-core'
import Dialog from './components/Dialog.vue' import Dialog from './components/Dialog.vue'
import gsap from 'gsap' import gsap from 'gsap'
import { ElMessage } from 'element-plus'
var rowData = [] var rowData = []
function getData(fn = () => {}) { function getData(fn = () => {}) {
// //
@ -97,7 +102,8 @@ export default {
bookMark: rowData[0].children, bookMark: rowData[0].children,
searchVal: '', searchVal: '',
allData: flatten(rowData), allData: flatten(rowData),
isDetailVisible: false isDetailVisible: false,
detail: {}
}) })
// //
@ -119,17 +125,43 @@ export default {
const navigate = (v) => window.open(v.url, '_target') const navigate = (v) => window.open(v.url, '_target')
// //
const add = () => (data.isDetailVisible = !data.isDetailVisible) function add(row = {}, flag = 'add') {
const temp = {...row}
if (flag === 'modify') {
data.detail = Object.assign(temp, { type: rowData[data.activeIndex].type, flag: 'modify' })
} else {
data.detail = Object.assign({}, { type: rowData[data.activeIndex].type, flag: 'add' })
}
data.isDetailVisible = true
}
// //
const closeViews = (v) => (data.isDetailVisible = v) const closeViews = (v) => (data.isDetailVisible = v)
//
const search = async () => { const search = async () => {
console.log('---->')
await getData(() => { await getData(() => {
data.data = rowData
data.bookMark = rowData[data.activeIndex].children data.bookMark = rowData[data.activeIndex].children
}) })
} }
//
const deleteClick = (row) => {
const myData = JSON.parse(localStorage.getItem('BOOKMARK'))
const delDetail = Object.assign(row, { type: rowData[data.activeIndex].type })
for (let i = 0; i < myData.length; i++) {
if (delDetail.type === myData[i].type) {
const cindex = myData[i].children.findIndex(s => s.title === delDetail.title)
if (cindex > -1) {
myData[i].children.splice(cindex, 1)
localStorage.setItem('BOOKMARK', JSON.stringify(myData))
ElMessage.success('删除成功')
search()
}
}
}
}
return { return {
deleteClick,
...toRefs(data), ...toRefs(data),
selectType, selectType,
navigate, navigate,
@ -251,6 +283,9 @@ export default {
animation: 0.3ms; animation: 0.3ms;
box-shadow: 0 8px 18px 0 rgba(31, 38, 135, 0.3); box-shadow: 0 8px 18px 0 rgba(31, 38, 135, 0.3);
} }
&:hover .logo-box-tools{
opacity: 0.85;
}
} }
} }
} }
@ -329,7 +364,7 @@ export default {
.logo-img { .logo-img {
width: 62px; width: 62px;
height: 100%; height: 100%;
margin-right: 14px; margin-right: 10px;
img { img {
height: 100%; height: 100%;
width: 100%; width: 100%;
@ -340,10 +375,11 @@ export default {
} }
} }
.logo-box { .logo-box {
position: relative;
flex: 1; flex: 1;
.title { .title {
width: 100%; width: 100%;
max-width: 190px; max-width: 145px;
display: block; display: block;
padding-top: 3px; padding-top: 3px;
font-size: 16px; font-size: 16px;
@ -402,4 +438,21 @@ export default {
width: 100%; width: 100%;
background: url(./assets/bg.jpg); background: url(./assets/bg.jpg);
} }
.logo-box-tools {
position: absolute;
right: 0;
top: 0;
opacity: 0;
transition:0.4s opacity;
i {
padding: 4px;
display: inline-block;
&:hover {
color: #e03b5d;
background: #ff00001f;
border-radius: 5px;
}
}
}
</style> </style>

View File

@ -41,8 +41,9 @@
</template> </template>
<script> <script>
import gsap from 'gsap' import gsap from 'gsap'
import { reactive, ref } from '@vue/reactivity' import { reactive, ref, toRefs } from '@vue/reactivity'
import { nextTick } from '@vue/runtime-core' import { nextTick, watch } from '@vue/runtime-core'
import { ElMessage } from 'element-plus'
export default { export default {
model: { model: {
value: 'isDetailVisible', value: 'isDetailVisible',
@ -56,17 +57,23 @@ export default {
selectType: { selectType: {
type: Number, type: Number,
default: 0 default: 0
},
detail: {
type: Object,
default: () => {}
} }
}, },
setup(props, context) { setup(props, context) {
const isBOOKMARK = JSON.parse(localStorage.getItem('BOOKMARK')) const isBOOKMARK = JSON.parse(localStorage.getItem('BOOKMARK'))
const BOOKMARK = isBOOKMARK ? isBOOKMARK.map((v) => v.type) : [] const BOOKMARK = isBOOKMARK ? isBOOKMARK.map((v) => v.type) : []
const ruleForm = reactive({ const form = reactive({
ruleForm: {
title: '', title: '',
type: '', type: '',
desc: '', desc: '',
url: '', url: '',
logo: '' logo: ''
}
}) })
// :rules // :rules
const rules = { const rules = {
@ -75,37 +82,70 @@ export default {
} }
const refruleForm = ref(null) const refruleForm = ref(null)
// //
console.log('--->', isBOOKMARK)
const submitForm = () => { const submitForm = () => {
refruleForm.value.validate((valid) => { refruleForm.value.validate((valid) => {
if (valid) { if (valid) {
console.log(isBOOKMARK)
const myData = isBOOKMARK.map((v) => { const myData = isBOOKMARK.map((v) => {
if (v.type === ruleForm.type) { const myDetail = { ...props.detail }
v.children.push({ ...ruleForm }) const formData = { ...form.ruleForm }
if (props.detail.flag === 'modify') {
//
if (myDetail.type === formData.type && v.type === formData.type) {
const sIndex = v.children.findIndex(
(d) => d.title === myDetail.title
)
if (sIndex > -1) {
v.children[sIndex] = formData
ElMessage.success('编辑成功')
}
} else if (myDetail.type !== formData.type) {
//
//
if (myDetail.type === v.type) {
const pindex = v.children.findIndex(p => p.title === myDetail.title)
v.children.splice(pindex, 1)
}
//
if (formData.type === v.type) {
v.children.push(formData)
ElMessage.success('编辑成功')
}
}
} else {
//
console.log('---?')
if (v.type === formData.type) {
v.children.push(formData)
ElMessage.success('新增成功')
}
} }
return v return v
}) })
console.log(myData)
localStorage.setItem('BOOKMARK', JSON.stringify(myData)) localStorage.setItem('BOOKMARK', JSON.stringify(myData))
context.emit('fresh') context.emit('fresh')
closeViews() closeViews()
} else {
return false
} }
}) })
} }
//
function closeViews() { function closeViews() {
refruleForm.value.resetFields() refruleForm.value.resetFields()
context.emit('closeViews', false) context.emit('closeViews', false)
} }
// //
watch(
() => props.detail,
(v) => {
if (v) {
nextTick(() => { nextTick(() => {
ruleForm.type = isBOOKMARK ? BOOKMARK[props.selectType] : '' form.ruleForm = { ...props.detail }
}) })
}
},
{ deep: true }
)
return { return {
ruleForm, ...toRefs(form),
closeViews, closeViews,
submitForm, submitForm,
refruleForm, refruleForm,