新增卡片拖拽

This commit is contained in:
zouzhibin 2022-04-29 22:11:15 +08:00
parent 4f27d9489c
commit a0c8cd815a
7 changed files with 360 additions and 47 deletions

View File

@ -13,12 +13,12 @@ const chartsRouter = {
roles:['other']
},
children: [
{
path: 'map',
component: () => import('@/views/charts/map.vue'),
name: 'map',
meta: { title: '地图', noCache: true , roles:['other'] }
},
// {
// path: 'map',
// component: () => import('@/views/charts/map.vue'),
// name: 'map',
// meta: { title: '地图', noCache: true , roles:['other'] }
// },
{
path: 'migration',
component: () => import('@/views/charts/migration.vue'),

View File

@ -8,7 +8,7 @@ const othersRouter = {
redirect: 'noRedirect',
name: 'other',
meta: {
title: '其他',
title: '扩展',
icon: 'management'
},
children: [
@ -28,13 +28,13 @@ const othersRouter = {
path: 'grid-sorter',
component: () => import('@/views/other/grid-sorter.vue'),
name: 'grid-sorter',
meta: { title: '网格排序', noCache: true }
meta: { title: '卡片拖拽', noCache: true }
},
{
path: 'splitpane',
component: () => import('@/views/other/splitpane.vue'),
name: 'splitpane',
meta: { title: 'splitpane', noCache: true }
meta: { title: '分割模块', noCache: true }
},
]

View File

@ -14,9 +14,9 @@ const tableRouter = {
},
children: [
{
path: 'complex',
component: () => import('@/views/table/complex.vue'),
name: 'complex',
path: 'comprehensive',
component: () => import('@/views/table/comprehensive.vue'),
name: 'comprehensive',
meta: { title: '综合表格', noCache: true }
},
{

View File

@ -93,11 +93,11 @@
.hideSidebar {
.sidebar-container {
width: 54px !important;
width: 60px !important;
}
.main-container {
margin-left: 54px;
margin-left: 60px;
}
.submenu-title-noDropdown {

View File

@ -1,12 +1,13 @@
<template>
<div class="row">
<div style="margin-bottom: 10px">网格拖拽排序</div>
<div style="margin-bottom: 10px">卡片拖拽排序</div>
<el-button class="btn " @click="sorter" type="primary" style="margin-bottom: 20px">
还原
</el-button>
<div class="col-6" style="max-width: 1200px">
<div class="col-6" style="">
<el-row :gutter="10">
<draggable
class="list-group"
tag="transition-group"
@ -22,22 +23,37 @@
item-key="order"
>
<template #item="{ element }">
<li class="list-group-item" :style="{backgroundColor:`${element.color}` }">
<i
:class="
element.fixed ? 'fa fa-anchor' : 'glyphicon glyphicon-pushpin'
"
@click="element.fixed = !element.fixed"
aria-hidden="true"
></i>
{{ element.name }}
</li>
<el-col :xs="12" :sm="6" :md="6" :lg="6" :xl="6"
>
<el-card shadow="hover" style="width: 100%" class="list-group-item">
<el-icon :size="30"
:color="element.color"
style="width: 100%;display: flex;justify-content: center">
<component :is="element.icon"></component>
</el-icon>
<div style="margin-top: 10px">按住拖拽排序</div>
</el-card>
</el-col>
</template>
</draggable>
</el-row>
</div>
</div>
</template>
<!--<li class="list-group-item" :style="{backgroundColor:`${element.color}` }">-->
<!-- <i-->
<!-- :class="-->
<!-- element.fixed ? 'fa fa-anchor' : 'glyphicon glyphicon-pushpin'-->
<!-- "-->
<!-- @click="element.fixed = !element.fixed"-->
<!-- aria-hidden="true"-->
<!-- ></i>-->
<!-- {{ element.name }}-->
<!--</li>-->
<script lang="ts" setup>
// https://sortablejs.github.io/vue.draggable.next/#/transition-example-2
// https://github.com/SortableJS/vue.draggable.next/blob/master/package.json
@ -46,14 +62,26 @@
import {getColor} from '@/utils/index'
const message = ref([]);
for(let i=0;i<28;i++){
let icon = ['management','baseball','Basketball','BellFilled','Bell',
'AddLocation','Aim','AlarmClock','Apple','ArrowDownBold','Burger',
'Brush','BrushFilled','RemoveFilled','QuestionFilled','Promotion','Printer',
'School','Setting','WarningFilled','ZoomOut','WalletFilled','User',
'ToiletPaper','Sunrise','Sunny','SwitchButton','TakeawayBox','Ticket',
'StarFilled','Stamp','Stopwatch','SortDown','SemiSelect','Search',
]
//
for(let i=0;i<30;i++){
message.value.push({
name:i,
order:i+1,
icon:icon[i],
color:getColor()
})
}
const drag = ref(false)
//
@ -74,18 +102,18 @@
<style lang="scss" scoped>
.list-group-item {
position: relative;
width: 100px;
/*width: 100px;*/
min-width: 160px;
margin-right: 10px;
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: center;
min-height: 100px;
padding: 0.75rem 1.25rem;
/*padding: 0.75rem 1.25rem;*/
background-color: #fff;
color: white;
font-weight: 500;
font-size: 24px;
/*font-size: 24px;*/
border: 1px solid rgba(0,0,0,.125);
}
.button {
@ -101,20 +129,20 @@
opacity: 0.5;
background: #c8ebfb;
}
.list-group {
display: flex;
display: -webkit-box;
display: flex;
-ms-flex-direction: column;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
//flex-direction: column;
padding-left: 0;
flex-wrap: wrap;
margin-bottom: 0;
border-radius: 0.25rem;
/*.list-group {*/
/* display: flex;*/
/* display: -webkit-box;*/
/* display: flex;*/
/* -ms-flex-direction: column;*/
/* -webkit-box-orient: vertical;*/
/* -webkit-box-direction: normal;*/
/* //flex-direction: column;*/
/* padding-left: 0;*/
/* flex-wrap: wrap;*/
/* margin-bottom: 0;*/
/* border-radius: 0.25rem;*/
}
/*}*/
.list-group-item {
cursor: move;
}

View File

@ -32,7 +32,7 @@
<slot name="btn"></slot>
</div>
<el-table
@selection-change="(val)=>$emit('selection-change',val)"
@selection-change="(val)=>emit('selection-change',val)"
:data="list"
style="width: 100%"
:border="true">
@ -66,7 +66,7 @@ import {computed, ref} from "vue";
import { ElMessage,ElMessageBox } from 'element-plus'
import type { FormInstance } from 'element-plus'
const ruleFormRef = ref<FormInstance>()
const emit = defineEmits(['reset','onSubmit'])
const emit = defineEmits(['reset','onSubmit','selection-change'])
let props = defineProps({
columns:{
type:Array,
@ -144,6 +144,7 @@ const deleteAction = (row)=>{
.then(() => {
list.value = list.value.filter(item=>item.id!==row.id)
ElMessage.success('删除成功')
})
.catch(() => {

View File

@ -0,0 +1,284 @@
<template>
<div class="app-container">
<comprehensive-table
@selection-change="selectionChange"
:columns="column" :data="list" @reset="reset" @onSubmit="onSubmit">
<template v-slot:btn>
<div style="display: flex;justify-content: flex-end">
<el-button type="primary" @click="add"><el-icon><plus /></el-icon> </el-button>
<el-button type="danger" @click="batchDelete"><el-icon><delete /></el-icon></el-button>
</div>
</template>
<template v-slot:sex="scope">{{scope.row.sex?'男':'女'}}</template>
<template v-slot:operation="scope">
<el-button
type="primary"
size="small"
icon="Edit"
@click="edit(scope.row)"
>
编辑
</el-button>
<el-button
@click="del(scope.row)"
type="danger"
size="small"
icon="Delete"
>
删除
</el-button>
</template>
</comprehensive-table>
<el-dialog
v-model="dialogVisible"
:title="title"
width="50%"
>
<el-form
ref="ruleFormRef"
:model="ruleForm"
:rules="rules"
label-width="120px"
class="demo-ruleForm"
:size="formSize"
>
<el-form-item label="活动名称" prop="name">
<el-input v-model="ruleForm.name" />
</el-form-item>
<el-form-item label="性别" prop="sex">
<el-radio-group v-model="ruleForm.sex">
<el-radio :label="1" ></el-radio>
<el-radio :label="0" ></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="价格" prop="price">
<el-input v-model="ruleForm.price" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleClose(ruleFormRef)"
>确定</el-button
>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import {ref,reactive} from "vue";
import * as dayjs from 'dayjs'
import { ElMessage,ElMessageBox } from 'element-plus'
import type { FormInstance } from 'element-plus'
import ComprehensiveTable from './components/comprehensive.vue'
const data = []
for(let i=0;i<100;i++){
data.push({
date: '2016-05-02',
name: '王五'+i,
price: 1+i,
province: '上海',
admin:"admin",
sex:i%2?1:0,
checked:true,
id:i+1,
age:0,
city: '普陀区',
address: '上海市普上海',
zip: 200333
})
}
const column = [
{ type:'selection', width:60 },
{ name: 'id', label: 'id',width:80, },
{ name: 'name',
label: '姓名',
inSearch:true,
valueType:'input',
width:80
},
{ name: 'age',
label: '年龄',
align:'right',
},
{ name: 'sex',
label: '性别',
slot:true,
inSearch:true,
options:[{
value:1,
label:'男'
},{
value:0,
label:'女'
}],
valueType:'select',
},
{
name: 'price',
label: '价格',
inSearch:true,
valueType:'input',
},
{ name: 'admin', label: '账号', inSearch:true,
valueType:'input',},
{ name: 'address', label: '地址', inSearch:true,
valueType:'input', },
{ name: 'date', label: '日期',sorter:true, inSearch:true,
valueType:'input', },
{ name: 'province', label: '省份' },
{ name: 'city', label: '城市' },
{ name: 'zip', label: '邮编' },
{ name: 'operation',slot:true,fixed:'right',width:200 }
]
const list = ref(data)
const formSize = ref('default')
const ruleFormRef = ref<FormInstance>()
const ruleForm = reactive({
name: '',
sex: null,
price:null,
})
const rules = reactive({
name: [
{ required: true, message: '请输入活动名称活动区域', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' },
],
price:[
{ required: true, message: '请输入价格', trigger: 'blur' },
],
sex: [
{
required: true,
message: '请选择性别',
trigger: 'change',
},
],
})
const dialogVisible = ref(false)
const title = ref('新增')
const rowObj = ref({})
const selectObj = ref([])
const handleClose = async (done: () => void) => {
await ruleFormRef.value.validate((valid, fields) => {
if (valid) {
let obj = {
id:Date.now(),
...ruleForm,
age:0,
city: '普陀区',
address: '上海市普上海',
zip: 200333,
province: '上海',
admin:"admin",
date: dayjs().format('YYYY-MM-DD')
}
if(title.value==='新增'){
list.value = [obj,...list.value]
ElMessage.success('添加成功')
}else {
list.value.forEach(item=>{
if(item.id===rowObj.value.id){
item.name=obj.name
item.sex=obj.sex
item.price=obj.price
}
})
}
dialogVisible.value = false
console.log('submit!',obj)
} else {
console.log('error submit!', fields)
}
})
}
const add = ()=>{
title.value='新增'
dialogVisible.value = true
}
const batchDelete = ()=>{
if(!selectObj.value.length){
return ElMessage.error('未选中任何行')
}
ElMessageBox.confirm(
'你确定要删除选中项吗?',
'温馨提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
draggable: true,
}
)
.then(() => {
ElMessage.success('模拟删除成功')
list.value = list.value.concat([])
})
.catch(() => {
})
}
const selectionChange = (val)=>{
selectObj.value = val
}
const edit = (row)=>{
title.value='编辑'
rowObj.value = row
dialogVisible.value = true
ruleForm.name = row.name
ruleForm.sex = row.sex
ruleForm.price = row.price
}
const del = (row)=>{
console.log('row==',row)
ElMessageBox.confirm(
'你确定要删除当前项吗?',
'温馨提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
draggable: true,
}
)
.then(() => {
list.value = list.value.filter(item=>item.id!==row.id)
ElMessage.success('删除成功')
})
.catch(() => {
})
}
const reset = ()=>{
ElMessage.success('触发重置方法')
}
const onSubmit = (val)=>{
console.log('val===',val)
ElMessage.success('触发查询方法')
}
</script>
<style scoped>
.edit-input {
padding-right: 100px;
}
.cancel-btn {
position: absolute;
right: 15px;
top: 10px;
}
</style>