- App 不统一包卡片(会与页面级卡片叠加),改由各页面根节点提供,与 Notice 一致 - 25 个视图套 .page-wrapper.yh-fill > .main-container;日志管理重写为 .search-wrap + .table-region + .page-panel 规范结构(卡片自动转 flex 纵向) - 新增 element_height mixin:ResizeObserver 实测 .table-region 高度喂 Table, 替代视口高度减常量的旧模型 - self_viewport 高度基准扣除卡片留白 64px,避免表格溢出被卡片裁切 - .env.dev 恢复真实后端地址
673 lines
20 KiB
Vue
673 lines
20 KiB
Vue
<template>
|
||
<div class="page-wrapper yh-fill">
|
||
<div class="main-container">
|
||
<div class="page-wrap">
|
||
<Tabs v-model="activeTab">
|
||
<TabPane label="校区管理" name="campus"></TabPane>
|
||
<TabPane label="系部管理" name="dept"></TabPane>
|
||
<TabPane label="专业管理" name="major"></TabPane>
|
||
</Tabs>
|
||
|
||
<!-- ====================== 校区管理【hover显示删除】 ====================== -->
|
||
<div v-if="activeTab === 'campus'" class="tab-panel">
|
||
<div class="btn-container">
|
||
<draggable
|
||
v-model="campuslist"
|
||
item-key="name"
|
||
:animation="150"
|
||
ghost-class="drag-ghost"
|
||
class="drag-box"
|
||
group="people"
|
||
@start="drag = true"
|
||
@end="drag = false"
|
||
:move="getdata1"
|
||
@change="datadragEnd1"
|
||
>
|
||
<template #item="{ element, index }">
|
||
<div class="tag-wrap" @dblclick="openEditModal('campus', index)">
|
||
<div class="tag-btn">{{ element.name }}</div>
|
||
<span class="close-btn" @click.stop="delCampus(index)">×</span>
|
||
</div>
|
||
</template>
|
||
</draggable>
|
||
<Button icon="ios-add" size="large" class="add-btn" @click="openAddModal('campus')">添加校区</Button>
|
||
</div>
|
||
<div class="tip-info">
|
||
<Icon type="ios-information-circle-outline"></Icon>
|
||
双击编辑,拖动排序
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ====================== 系部管理【hover显示删除】 ====================== -->
|
||
<div v-if="activeTab === 'dept'" class="tab-panel">
|
||
<div class="btn-container">
|
||
<draggable
|
||
v-model="divisionlist"
|
||
item-key="name"
|
||
:animation="150"
|
||
ghost-class="drag-ghost"
|
||
class="drag-box"
|
||
group="people"
|
||
@start="drag = true"
|
||
@end="drag = false"
|
||
:move="getdata2"
|
||
@change="datadragEnd2"
|
||
>
|
||
<template #item="{ element, index }">
|
||
<div class="tag-wrap" @dblclick="openEditModal('dept', index)">
|
||
<div class="tag-btn">{{ element.name }}</div>
|
||
<span class="close-btn" @click.stop="delDept(index)">×</span>
|
||
</div>
|
||
</template>
|
||
</draggable>
|
||
<Button icon="ios-add" size="large" class="add-btn" @click="openAddModal('dept')">添加系部</Button>
|
||
</div>
|
||
<div class="tip-info">
|
||
<Icon type="ios-information-circle-outline"></Icon>
|
||
双击编辑,拖动排序
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ====================== 专业管理【修复拖拽失效】 ====================== -->
|
||
<div v-if="activeTab === 'major'" class="tab-panel major-adapt-wrap">
|
||
<div class="major-top-bar">
|
||
<Button type="primary" icon="ios-add" @click="openMajorAdd">添加专业</Button>
|
||
<div class="search-box">
|
||
<i-Input
|
||
v-model="majorKeyword"
|
||
placeholder="输入代码或名称搜索"
|
||
@keyup.enter="searchMajor"
|
||
>
|
||
<template #suffix><Icon type="ios-search" @click="searchMajor" style="cursor:pointer;"></Icon></template>
|
||
</i-Input>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="table-scroll-box" ref="tableBoxRef">
|
||
<Table
|
||
stripe
|
||
:columns="majorColumns"
|
||
:data="majorTableData"
|
||
class="major-table"
|
||
ref="tableRef"
|
||
></Table>
|
||
</div>
|
||
|
||
<!-- <div class="pagination-fixed-bottom">
|
||
<span class="total-desc">共 {{ majorTotal }} 条</span>
|
||
<Page
|
||
v-model="majorPageNum"
|
||
:total="majorTotal"
|
||
:page-size="majorPageSize"
|
||
:page-size-opts="[10,20,50]"
|
||
show-sizer
|
||
@on-change="majorPageChange"
|
||
@on-page-size-change="majorSizeChange"
|
||
></Page>
|
||
</div> -->
|
||
</div>
|
||
|
||
<!-- 校区/系部 新增编辑弹窗 -->
|
||
<Modal v-model="modalVisible" :title="modalTitle" width="420">
|
||
<Form ref="formRef" :model="formData" :rules="formRule" :label-width="90">
|
||
<FormItem label="校区名称" v-if="modalType === 'campus'" prop="name">
|
||
<Input v-model="formData.name" placeholder="请输入校区名称" />
|
||
</FormItem>
|
||
<FormItem label="系部名称" v-if="modalType === 'dept'" prop="name">
|
||
<Input v-model="formData.name" placeholder="请输入系部名称" />
|
||
</FormItem>
|
||
</Form>
|
||
<template #footer><div align="right">
|
||
<Button @click="modalVisible = false" style="margin-right: 10px">取消</Button>
|
||
<Button type="primary" @click="submitModal">提交</Button>
|
||
</div></template>
|
||
</Modal>
|
||
|
||
<!-- 专业新增编辑弹窗 -->
|
||
<Modal v-model="majorModalVisible" :title="majorModalTitle" width="460">
|
||
<Form ref="majorFormRef" :model="majorForm" :rules="majorFormRule" :label-width="90">
|
||
<FormItem label="专业代码">
|
||
<Input v-model="majorForm.code" placeholder="请输入专业代码" />
|
||
</FormItem>
|
||
<FormItem label="专业名称" prop="name">
|
||
<Input v-model="majorForm.name" placeholder="请输入专业名称" />
|
||
</FormItem>
|
||
<FormItem label="学制" prop="schsystemLeng">
|
||
<Input v-model="majorForm.schsystemLeng" type="number" placeholder="请输入学制" />
|
||
</FormItem>
|
||
</Form>
|
||
<template #footer><div align="right">
|
||
<Button @click="majorModalVisible = false" style="margin-right: 10px">取消</Button>
|
||
<Button type="primary" @click="submitMajorModal">提交</Button>
|
||
</div></template>
|
||
</Modal>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { Button, Icon } from "view-ui-plus";
|
||
import draggable from 'vuedraggable'
|
||
import Sortable from 'sortablejs'
|
||
export default {
|
||
name: 'SchoolSetting',
|
||
components: { draggable },
|
||
data() {
|
||
return {
|
||
activeTab: 'campus',
|
||
campuslist: [],
|
||
divisionlist: [],
|
||
|
||
modalVisible: false,
|
||
modalType: '',
|
||
modalTitle: '',
|
||
editIndex: null,
|
||
formData: { id:0,name:'' },
|
||
formRule: {
|
||
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }]
|
||
},
|
||
|
||
majorKeyword: '',
|
||
majorPageNum: 1,
|
||
majorPageSize: 10,
|
||
majorTotal: 22,
|
||
majorColumns: [
|
||
{
|
||
title: '序号',
|
||
key: '_index',
|
||
align: 'center',
|
||
width: 70,
|
||
render: (h, params) => h('span', params.index + 1)
|
||
},
|
||
{ title: 'ID', key: 'id', align: 'center' },
|
||
{ title: '专业代码', key: 'code', align: 'center' },
|
||
{ title: '专业名称', key: 'name', align: 'center' },
|
||
{ title: '学制', key: 'schsystemLeng', align: 'center' },
|
||
{
|
||
title: '操作',
|
||
key: 'action',
|
||
align: 'center',
|
||
width: 170,
|
||
render: (h, params) => {
|
||
return h('div', { style: 'display:flex;gap:8px;justify-content:center;align-items:center' }, [
|
||
h(Button, {type: 'text', icon: 'ios-create', size: 'small',
|
||
onClick: () => this.openMajorEdit(params.index)}),
|
||
h(Button, {type: 'text', icon: 'ios-trash', size: 'small',
|
||
onClick: () => this.delMajor(params.index)}),
|
||
// 拖拽把手class固定为 drag-handle
|
||
h(Icon, {type: 'ios-move', size: 18, title: '拖动排序',
|
||
class: 'drag-handle drag-icon'})
|
||
])
|
||
}
|
||
}
|
||
],
|
||
majorTableData: [],
|
||
majorModalVisible: false,
|
||
majorModalTitle: '',
|
||
majorEditIndex: null,
|
||
majorForm: { code: '', name: '', schsystemLeng: '' },
|
||
majorFormRule: {
|
||
code: [{ required: true, message: '专业代码不能为空', trigger: 'blur' }],
|
||
name: [{ required: true, message: '专业名称不能为空', trigger: 'blur' }],
|
||
schsystemLeng: [{ required: true, message: '学制不能为空', trigger: 'blur' }]
|
||
},
|
||
tableDrag: null
|
||
}
|
||
},
|
||
watch: {
|
||
// 切换标签页重新初始化拖拽
|
||
activeTab(val) {
|
||
if (val === 'major') {
|
||
this.$nextTick(() => this.initTableDrag())
|
||
this.getmajorslist();
|
||
} else if(val === 'campus') {
|
||
if (this.tableDrag) this.tableDrag.destroy();
|
||
this.getcampuslist();
|
||
}else{
|
||
if (this.tableDrag) this.tableDrag.destroy();
|
||
this.getdivisionlist();
|
||
}
|
||
}
|
||
},
|
||
created(){
|
||
this.getcampuslist();
|
||
},
|
||
mounted() {
|
||
// 延时确保表格完全渲染完毕再初始化
|
||
setTimeout(() => {
|
||
if (this.activeTab === 'major') {
|
||
this.initTableDrag()
|
||
}
|
||
}, 120)
|
||
},
|
||
beforeUnmount() {
|
||
if (this.tableDrag) this.tableDrag.destroy()
|
||
},
|
||
methods: {
|
||
//获取学校分校列表
|
||
getcampuslist() {
|
||
const _this = this;
|
||
var item = {};
|
||
_this.$api.get(APIConfig.BschClassSystem.getcampuslist, item, resp => {
|
||
if (resp.code == 0) {
|
||
_this.campuslist = resp.data;
|
||
} else {
|
||
_this.campuslist = [];
|
||
}
|
||
});
|
||
},
|
||
//获取系部列表
|
||
getdivisionlist() {
|
||
const _this = this;
|
||
var item = {};
|
||
_this.$api.get(APIConfig.BschClassSystem.getdivisionlist, item, resp => {
|
||
if (resp.code == 0) {
|
||
_this.divisionlist = resp.data;
|
||
} else {
|
||
_this.divisionlist = [];
|
||
}
|
||
});
|
||
},
|
||
//获取专业列表
|
||
getmajorslist() {
|
||
const _this = this;
|
||
var item = {
|
||
keyword:_this.majorKeyword
|
||
};
|
||
_this.$api.get(APIConfig.BschClassSystem.getmajorslist, item, resp => {
|
||
if (resp.code == 0) {
|
||
_this.majorTableData = resp.data;
|
||
} else {
|
||
_this.majorTableData = [];
|
||
}
|
||
});
|
||
},
|
||
//校区拖动前
|
||
getdata1 (evt) {
|
||
//console.log(evt.draggedContext.element)
|
||
},
|
||
|
||
//校区拖动后
|
||
datadragEnd1 (evt) {
|
||
var _this=this;
|
||
//console.log('拖动后的索引 :' + evt.newIndex);
|
||
//console.log('拖动前的索引 :' + evt.oldIndex);
|
||
var ids=[],orders=[];
|
||
_this.campuslist.forEach(element => {
|
||
ids.push(element.id);
|
||
});
|
||
var url=APIConfig.BschClassSystem.campussort;
|
||
_this.$api.post(url,JSON.stringify(ids),(resp)=>{
|
||
_this.$Message.info('拖动排序成功!');
|
||
_this.getcampuslist();
|
||
});
|
||
},
|
||
//系部拖动前
|
||
getdata2 (evt) {
|
||
//console.log(evt.draggedContext.element)
|
||
},
|
||
|
||
//系部拖动后
|
||
datadragEnd2 (evt) {
|
||
var _this=this;
|
||
//console.log('拖动后的索引 :' + evt.newIndex);
|
||
//console.log('拖动前的索引 :' + evt.oldIndex);
|
||
var ids=[],orders=[];
|
||
_this.divisionlist.forEach(element => {
|
||
ids.push(element.id);
|
||
});
|
||
var url=APIConfig.BschClassSystem.divisionsort;
|
||
_this.$api.post(url,JSON.stringify(ids),(resp)=>{
|
||
_this.$Message.info('拖动排序成功!');
|
||
_this.getdivisionlist();
|
||
});
|
||
},
|
||
// 表格拖拽初始化【修复关键点】
|
||
initTableDrag() {
|
||
if (this.tableDrag) {
|
||
this.tableDrag.destroy()
|
||
this.tableDrag = null
|
||
}
|
||
const tableEl = this.$refs.tableRef?.$el
|
||
if (!tableEl) return
|
||
const tbody = tableEl.querySelector('tbody')
|
||
if (!tbody) return
|
||
|
||
this.tableDrag = new Sortable(tbody, {
|
||
animation: 0, // 关闭Sortable自带DOM位移动画
|
||
swap: false,
|
||
handle: '.drag-handle',
|
||
ghostClass: 'table-drag-ghost',
|
||
preventOnFilter: true,
|
||
// 关键:Sortable只计算下标,不改动页面DOM结构
|
||
forceAutoScroll: true,
|
||
onEnd: (evt) => {
|
||
const oldIndex = evt.oldIndex
|
||
const newIndex = evt.newIndex
|
||
if (oldIndex === newIndex) return
|
||
|
||
// ========== 关键 1:撤销 Sortable 的 DOM 操作 ==========
|
||
const tbody = evt.to
|
||
const rows = Array.from(tbody.querySelectorAll('tr'))
|
||
// 计算元素原来应该插回的位置
|
||
const refIndex = oldIndex < newIndex ? oldIndex : oldIndex + 1
|
||
const refNode = rows[refIndex]
|
||
if (refNode) {
|
||
tbody.insertBefore(evt.item, refNode)
|
||
} else {
|
||
tbody.appendChild(evt.item)
|
||
}
|
||
// ========== 关键 2:用 splice 移动数组元素(不是交换!) ==========
|
||
const movedItem = this.majorTableData[oldIndex]
|
||
this.majorTableData.splice(oldIndex, 1)
|
||
this.majorTableData.splice(newIndex, 0, movedItem)
|
||
|
||
// ========== 后端排序接口 ==========
|
||
const ids = this.majorTableData.map(item => item.id)
|
||
const url = APIConfig.BschClassSystem.majorssort
|
||
this.$api.post(url, JSON.stringify(ids), (resp) => {
|
||
this.$Message.info('拖动排序成功!');
|
||
})
|
||
}
|
||
})
|
||
},
|
||
|
||
// ========== 校区删除 ==========
|
||
delCampus(index) {
|
||
this.$Modal.confirm({
|
||
title: '提示',
|
||
content: '确定删除该校区?',
|
||
onOk: () => {
|
||
var url=APIConfig.BschClassSystem.campusdelete+this.campuslist[index].id;
|
||
this.$api.post(url,{},(resp)=>{
|
||
this.$Message.success('删除成功!');
|
||
this.getcampuslist();
|
||
});
|
||
}
|
||
})
|
||
},
|
||
// ========== 系部删除 ==========
|
||
delDept(index) {
|
||
this.$Modal.confirm({
|
||
title: '提示',
|
||
content: '确定删除该系部?',
|
||
onOk: () => {
|
||
var url=APIConfig.BschClassSystem.divisiondelete+this.divisionlist[index].id;
|
||
this.$api.post(url,{},(resp)=>{
|
||
this.$Message.success('删除成功!');
|
||
this.getdivisionlist();
|
||
});
|
||
}
|
||
})
|
||
},
|
||
|
||
// ========== 校区/系部 弹窗逻辑 ==========
|
||
openAddModal(type) {
|
||
this.modalType = type;
|
||
this.editIndex = null;
|
||
this.formData.id = 0;
|
||
this.formData.name = '';
|
||
this.modalTitle = type === 'campus' ? '新增校区' : '新增系部';
|
||
this.modalVisible = true;
|
||
this.$nextTick(() => this.$refs.formRef.clearValidate());
|
||
},
|
||
openEditModal(type, index) {
|
||
this.modalType = type;
|
||
this.editIndex = index;
|
||
const list = type === 'campus' ? this.campuslist : this.divisionlist;
|
||
this.formData = list[index];
|
||
this.modalTitle = type === 'campus' ? '校区信息' : '系部信息';
|
||
this.modalVisible = true;
|
||
this.$nextTick(() => this.$refs.formRef.clearValidate());
|
||
},
|
||
submitModal() {
|
||
this.$refs.formRef.validate(valid => {
|
||
if (!valid) return
|
||
const name = this.formData.name.trim()
|
||
const list = this.modalType === 'campus' ? this.campuslist : this.divisionlist;
|
||
const hasRepeat = list.some((item, i) => item.name === name && i !== this.editIndex);
|
||
if (hasRepeat) {
|
||
this.$Message.error('名称已存在,不能重复')
|
||
return
|
||
}
|
||
if (this.editIndex === null) {
|
||
const submitData = {
|
||
name: name
|
||
};
|
||
const url =this.modalType === 'campus' ? APIConfig.BschClassSystem.campussave:APIConfig.BschClassSystem.divisionsave;
|
||
this.$api.post(url, JSON.stringify(submitData), resp => {
|
||
if (resp.code == 0) {
|
||
this.$Message.success("添加成功!");
|
||
this.modalType === 'campus' ? this.getcampuslist() : this.getdivisionlist();
|
||
} else if (resp.code == 4) {
|
||
this.$Message.info(resp.msg);
|
||
}
|
||
});
|
||
} else {
|
||
const submitData = {
|
||
id:this.formData.id,
|
||
sort:this.formData.sort,
|
||
name: name
|
||
};
|
||
const url =this.modalType === 'campus' ? APIConfig.BschClassSystem.campussave:APIConfig.BschClassSystem.divisionsave;
|
||
this.$api.post(url, JSON.stringify(submitData), resp => {
|
||
if (resp.code == 0) {
|
||
this.$Message.success("修改成功!");
|
||
this.modalType === 'campus' ? this.getcampuslist() : this.getdivisionlist();
|
||
} else if (resp.code == 4) {
|
||
this.$Message.info(resp.msg);
|
||
}
|
||
});
|
||
}
|
||
this.modalVisible = false
|
||
})
|
||
},
|
||
|
||
// ========== 专业管理 ==========
|
||
openMajorAdd() {
|
||
this.majorEditIndex = null
|
||
this.majorForm = { code: '', name: '', schsystemLeng: '' }
|
||
this.majorModalTitle = '新增专业'
|
||
this.majorModalVisible = true
|
||
this.$nextTick(() => this.$refs.majorFormRef.clearValidate())
|
||
},
|
||
openMajorEdit(index) {
|
||
this.majorEditIndex = index
|
||
const row = this.majorTableData[index];
|
||
row.schsystemLeng=this.majorTableData[index].schsystemLeng+'';
|
||
this.majorForm = { ...row }
|
||
this.$nextTick(() => this.$refs.majorFormRef.clearValidate())
|
||
this.majorModalTitle = '编辑专业'
|
||
this.majorModalVisible = true
|
||
},
|
||
submitMajorModal() {
|
||
this.$refs.majorFormRef.validate(valid => {
|
||
if (!valid) return
|
||
if (this.majorEditIndex === null) {
|
||
const submitData =this.majorForm;
|
||
const url = APIConfig.BschClassSystem.majorssave;
|
||
this.$api.post(url, JSON.stringify(submitData), resp => {
|
||
if (resp.code == 0) {
|
||
this.$Message.success("新增专业成功!");
|
||
this.getmajorslist();
|
||
} else if (resp.code == 4) {
|
||
this.$Message.info(resp.msg);
|
||
}
|
||
});
|
||
} else {
|
||
const submitData =this.majorForm;
|
||
const url = APIConfig.BschClassSystem.majorssave;
|
||
this.$api.post(url, JSON.stringify(submitData), resp => {
|
||
if (resp.code == 0) {
|
||
this.$Message.success("编辑专业成功!");
|
||
this.getmajorslist();
|
||
} else if (resp.code == 4) {
|
||
this.$Message.info(resp.msg);
|
||
}
|
||
});
|
||
}
|
||
this.majorModalVisible = false
|
||
this.$nextTick(() => this.initTableDrag())
|
||
})
|
||
},
|
||
delMajor(index) {
|
||
this.$Modal.confirm({
|
||
title: '提示',
|
||
content: '确定删除该专业?',
|
||
onOk: () => {
|
||
var url=APIConfig.BschClassSystem.majorsdelete+this.majorTableData[index].id;
|
||
this.$api.post(url,{},(resp)=>{
|
||
this.$Message.success('删除成功!');
|
||
this.getmajorslist();
|
||
});
|
||
this.$nextTick(() => this.initTableDrag())
|
||
}
|
||
})
|
||
},
|
||
searchMajor() {
|
||
this.majorPageNum = 1
|
||
this.$nextTick(() => this.initTableDrag());
|
||
this.getmajorslist();
|
||
},
|
||
majorPageChange(page) {
|
||
this.majorPageNum = page
|
||
this.$nextTick(() => this.initTableDrag())
|
||
},
|
||
majorSizeChange(size) {
|
||
this.majorPageSize = size
|
||
this.majorPageNum = 1
|
||
this.$nextTick(() => this.initTableDrag())
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.page-wrap {
|
||
padding: 16px;
|
||
width: 100%;
|
||
height: 100%;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.page-title {
|
||
margin: 0 0 12px;
|
||
font-size: 18px;
|
||
font-weight: 500;
|
||
}
|
||
.tab-panel {
|
||
margin-top: 20px;
|
||
flex-shrink: 0;
|
||
}
|
||
.btn-container {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
gap: 16px;
|
||
}
|
||
.drag-box {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16px;
|
||
}
|
||
|
||
/* 悬浮删除容器 */
|
||
.tag-wrap {
|
||
position: relative;
|
||
cursor: move;
|
||
user-select: none;
|
||
}
|
||
.tag-btn {
|
||
border: 1px solid #666;
|
||
padding: 8px 22px;
|
||
border-radius: 2px;
|
||
}
|
||
.close-btn {
|
||
position: absolute;
|
||
top: -6px;
|
||
right: -6px;
|
||
width: 18px;
|
||
height: 18px;
|
||
border-radius: 50%;
|
||
background: #f56c6c;
|
||
color: #fff;
|
||
font-size: 14px;
|
||
text-align: center;
|
||
line-height: 18px;
|
||
display: none;
|
||
cursor: pointer;
|
||
}
|
||
.tag-wrap:hover .close-btn {
|
||
display: block;
|
||
}
|
||
|
||
.add-btn {
|
||
padding: 8px 22px;
|
||
}
|
||
.tip-info {
|
||
margin-top: 30px;
|
||
color: #999;
|
||
font-size: 13px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
}
|
||
::v-deep .drag-ghost {
|
||
opacity: 0.4;
|
||
background: #cde4ff;
|
||
}
|
||
|
||
/* 专业布局 */
|
||
.major-adapt-wrap {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
margin-top: 0px;
|
||
min-height: 0;
|
||
}
|
||
.major-top-bar {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 14px;
|
||
flex-shrink: 0;
|
||
background: #F7F7F7;
|
||
padding: 10px;
|
||
}
|
||
.search-box {
|
||
width: 260px;
|
||
}
|
||
.table-scroll-box {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
}
|
||
.major-table {
|
||
width: 100%;
|
||
}
|
||
.drag-icon {
|
||
cursor: move;
|
||
margin-left: 8px;
|
||
font-size: 18px;
|
||
}
|
||
/* 关键:穿透scoped,Sortable能识别把手 */
|
||
::v-deep .drag-handle {
|
||
cursor: grab !important;
|
||
}
|
||
::v-deep .table-drag-ghost {
|
||
background-color: #e8f3ff !important;
|
||
}
|
||
.pagination-fixed-bottom {
|
||
flex-shrink: 0;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
align-items: center;
|
||
margin-top: 14px;
|
||
gap: 12px;
|
||
}
|
||
.total-desc {
|
||
color: #666;
|
||
font-size: 13px;
|
||
}
|
||
</style> |