教程11 Vue3 + Django前后端分离项目——Element Plus Table 表格(数据增、删、改、除、分页)

目录

一、查询公告信息表中的数据,并绑定到表格中

1. 后端接口(http://127.0.0.1:8000/notices) 

2. utils/api.ts中增加如下函数,用于调用后端接口查询所有公告信息

3. views文件夹中新建一个NoticesManagement.vue文件

二、实现分页

1. 后端接口(http://127.0.0.1:8000/notices/1/2) 

2. utils/api.ts中增加函数,用于调用后端接口根据页码查询公告信息

3.  修改NoticesManagement.vue文件

三、删除

1. 后端接口(http://127.0.0.1:8000/delete_notice/1) 

2. utils/api.ts中增加函数,用于调用后端接口根据公告id删除公告信息

3.  修改NoticesManagement.vue文件

四、新增公告 

1. 后端接口(http://127.0.0.1:8000/add_notice) 

2. utils/api.ts中增加函数,用于调用后端接口增加公告信息

3.  修改NoticesManagement.vue文件

五、编辑公告 

1. 后端接口(http://127.0.0.1:8000/edit_notice/) 

2. utils/api.ts中增加函数,用于调用后端接口编辑公告信息

3.  修改NoticesManagement.vue文件

六、筛选公告

​编辑​1.  修改NoticesManagement.vue文件

七、多选

1.  修改NoticesManagement.vue文件

八、全选、清除、批量删除 

1.  修改NoticesManagement.vue文件

九、Excel导入导出

1. Excel导入

2. Excel导出

3. 安装依赖包

4.  Excel模板template.xlsx放入public文件夹中

5.   修改NoticesManagement.vue文件


一、查询公告信息表中的数据,并绑定到表格中

1. 后端接口(http://127.0.0.1:8000/notices) 

2. utils/api.ts中增加如下函数,用于调用后端接口查询所有公告信息

// 获得所有公告信息
export function getAllNoticesUrl() {
    return request({
        url: 'api/notices/',
        method: 'get',
    })
}

3. views文件夹中新建一个NoticesManagement.vue文件

<template>
  <h1>公告管理</h1>
  <el-table ref="tableNoticeRef" :data="tableDataNotices" style="width: 100%">
    <el-table-column prop="id" label="编号" width="180" v-if="true" />
    <el-table-column prop="title" label="标题" width="380">
      <template #default="scope" width="300">
        <span>{{ scope.row.title }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="user" label="发布人姓名" width="100">
      <template #default="scope" width="180">
        <span>{{ scope.row.user }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="content" label="内容" width="280">
      <template #default="scope" width="180">
        <span>{{ scope.row.content }}</span>
      </template>
    </el-table-column>
  </el-table>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { getAllNoticesUrl } from "../utils/api";
// 声明一个公告类型的接口
interface Notice {
  id: number; // 公告编号
  title: string; // 公告标题
  content: string; // 公告内容
  add_time: string; // 发布时间
  user_id: number; // 用户编号
  user: string; // 用户信息
}
// 公告数据
var tableDataNotices = ref<Notice[]>([]);
// 查询所有的公告并绑定到表格中
const getAllNoticesData = () => {
  getAllNoticesUrl().then((res: any) => {
    console.log(res);
    tableDataNotices.value = res.data;
   
  });
};
// 页面加载后查询所有公告数据
onMounted(() => {
  getAllNoticesData();
});
</script>

二、实现分页

1. 后端接口(http://127.0.0.1:8000/notices/1/2/) 

2. utils/api.ts中增加函数,用于调用后端接口根据页码查询公告信息

// 分页
export function getNoticesByPageUrl(params: any) {
    return request({
        url: 'api/notices/' + Number(params['currentPage']) + '/' + Number(params['pageSize']) + '/',
        method: 'get',
    })
}

3.  修改NoticesManagement.vue文件

<template>
  <h1>公告管理</h1>
  <el-table ref="tableNoticeRef" :data="tableDataNotices" style="width: 100%">
    <el-table-column prop="id" label="编号" width="180" v-if="true" />
    <el-table-column prop="title" label="标题" width="380">
      <template #default="scope" width="300">
        <span>{{ scope.row.title }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="user" label="发布人姓名" width="100">
      <template #default="scope" width="180">
        <span>{{ scope.row.user }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="content" label="内容" width="280">
      <template #default="scope" width="180">
        <span>{{ scope.row.content }}</span>
      </template>
    </el-table-column>
  </el-table>
  <!-- 分页组件 -->
  <el-pagination
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="pageSizes"
    :page-size="pageSize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
  >
  </el-pagination>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { getAllNoticesUrl, getNoticesByPageUrl } from "../utils/api";
// 声明一个公告类型的接口
interface Notice {
  id: number; // 公告编号
  title: string; // 公告标题
  content: string; // 公告内容
  add_time: string; // 发布时间
  user_id: number; // 用户编号
  user: string; // 用户信息
}
// 公告数据
var tableDataNotices = ref<Notice[]>([]);
// 查询所有的公告并绑定到表格中
// const getAllNoticesData = () => {
//   getAllNoticesUrl().then((res: any) => {
//     console.log(res);
//     tableDataNotices.value = res.data;
//     let total = tableDataNotices.value.length; // 修改总页数
//   });
// };

// 查询所有的公告并绑定到表格中(分页)
const getAllNoticesData = () => {
  let params = {
    currentPage: currentPage.value,
    pageSize: pageSize.value,
  };
  getNoticesByPageUrl(params).then((res: any) => {
    console.log(res);
    tableDataNotices.value = res.data;
    total.value = res.total; // 修改总页数
  });
};

// 页面加载后查询所有公告数据
onMounted(() => {
  getAllNoticesData();
});
// 分页
const pageSizes = [5, 10, 15, 20, 50, 100];
const pageSize = ref(5); // 每页记录条数
const currentPage = ref(1); // 当前页的索引
const small = ref(false);
const background = ref(false);
const disabled = ref(false);
const total = ref(0); // 总页数

// 分页
const handleSizeChange = (val: number) => {
  console.log("${val} items per page");
  pageSize.value = val;
  getAllNoticesData();
};

const handleCurrentChange = (val: number) => {
  console.log("current page: ${val}");
  currentPage.value = val;
  getAllNoticesData();
};
</script>

三、删除

1. 后端接口(http://127.0.0.1:8000/delete_notice/1) 

2. utils/api.ts中增加函数,用于调用后端接口根据公告id删除公告信息

// 删除公告
export function deleteNoticeUrl(params:any) {
    return request({
        url: 'api/delete_notice/' + params + "/",
        method: 'delete',
    })
}

3.  修改NoticesManagement.vue文件

<template>
  <h1>公告管理</h1>
  <el-table ref="tableNoticeRef" :data="tableDataNotices" style="width: 100%">
    <el-table-column prop="id" label="编号" width="180" v-if="true" />
    <el-table-column prop="title" label="标题" width="380">
      <template #default="scope" width="300">
        <span>{{ scope.row.title }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="user" label="发布人姓名" width="100">
      <template #default="scope" width="180">
        <span>{{ scope.row.user }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="content" label="内容" width="280">
      <template #default="scope" width="180">
        <span>{{ scope.row.content }}</span>
      </template>
    </el-table-column>

    <el-table-column label="操作" width="300">
                    <template #default="scope">
                        <div>
                            <el-popconfirm confirm-button-text="是" cancel-button-text="否" title="您确定删除吗?"
                                icon-color="#626AEF" @confirm="handleDelete(scope.row)">
                                <template #reference>
                                    <el-button>删除</el-button>
                                </template>
                            </el-popconfirm>                           
                        </div>
                    </template>
                </el-table-column>
  </el-table>
  <!-- 分页组件 -->
  <el-pagination
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="pageSizes"
    :page-size="pageSize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
  >
  </el-pagination>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import { getAllNoticesUrl, getNoticesByPageUrl, deleteNoticeUrl } from "../utils/api";
// 声明一个公告类型的接口
interface Notice {
  id: number; // 公告编号
  title: string; // 公告标题
  content: string; // 公告内容
  add_time: string; // 发布时间
  user_id: number; // 用户编号
  user: string; // 用户信息
}
// 公告数据
var tableDataNotices = ref<Notice[]>([]);
// 查询所有的公告并绑定到表格中
// const getAllNoticesData = () => {
//   getAllNoticesUrl().then((res: any) => {
//     console.log(res);
//     tableDataNotices.value = res.data;
//     let total = tableDataNotices.value.length; // 修改总页数
//   });
// };

// 查询所有的公告并绑定到表格中(分页)
const getAllNoticesData = () => {
  let params = {
    currentPage: currentPage.value,
    pageSize: pageSize.value,
  };
  getNoticesByPageUrl(params).then((res: any) => {
    console.log(res);
    tableDataNotices.value = res.data;
    total.value = res.total; // 修改总页数
  });
};

// 页面加载后查询所有公告数据
onMounted(() => {
  getAllNoticesData();
});
// 分页
const pageSizes = [5, 10, 15, 20, 50, 100];
const pageSize = ref(5); // 每页记录条数
const currentPage = ref(1); // 当前页的索引
const small = ref(false);
const background = ref(false);
const disabled = ref(false);
const total = ref(0); // 总页数

// 分页
const handleSizeChange = (val: number) => {
  console.log("${val} items per page");
  pageSize.value = val;
  getAllNoticesData();
};

const handleCurrentChange = (val: number) => {
  console.log("current page: ${val}");
  currentPage.value = val;
  getAllNoticesData();
};

//删除
const handleDelete = (row: Notice) => {
    let params = row.id;
    deleteNoticeUrl(params).then((res) => {
        console.log(res.data.meta);
        getAllNoticesData();
    });
};

/*
const handleDelete = (index: number, row: Notice) => {
  let params = row.id;
  deleteNotice(params);
};

const deleteNotice = async (params: any) => {
  try {
    const response = await deleteNoticeUrl(params);
    console.log(response.data.meta);
    getAllNoticesData();
  } catch (error) {
    console.error(error);
  }
};
*/
</script>

4. 添加删除对话框

 <el-popconfirm
    confirm-button-text="是"
    cancel-button-text="否"
    :icon="InfoFilled"
    icon-color="#626AEF"
    title="您确定要删除吗?"
    @confirm="handleDelete(scope.$index, scope.row)"
    @cancel="cancelEvent"
>
    <template #reference>
            <el-button>Delete</el-button>
    </template>
</el-popconfirm>
<script lang="ts" setup>
    ……
    import { InfoFilled } from '@element-plus/icons-vue'
    const cancelEvent = () => {
      console.log('cancel!')
    }
</script>

四、新增公告 

 

1. 后端接口(http://127.0.0.1:8000/add_notice) 

{
    "title": "会议通知",
    "content": "今天上午10:00,会议室开会,地点信息楼210",
    "user_id":"11"
}

2. utils/api.ts中增加函数,用于调用后端接口增加公告信息

// 新增公告
export function addNoticeUrl(data:any) {
    return request({
        url: 'api/add_notice/',
        method: 'post',
        data: data,
    })
}

3.  修改NoticesManagement.vue文件

<template>
  <h1>公告管理</h1>
  <el-row :gutter="20">
		<el-col :span="4">
			<template #default="scope">
				<el-button text :icon="Edit" @click="handleAdd()" v-permiss="15">
					新增
				</el-button>
			</template>
		</el-col>
	</el-row>
  <el-table ref="tableNoticeRef" :data="tableDataNotices" style="width: 100%">
    <el-table-column prop="id" label="编号" width="180" v-if="true" />
    <el-table-column prop="title" label="标题" width="380">
      <template #default="scope" width="300">
        <span>{{ scope.row.title }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="user" label="发布人姓名" width="100">
      <template #default="scope" width="180">
        <span>{{ scope.row.user }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="content" label="内容" width="280">
      <template #default="scope" width="180">
        <span>{{ scope.row.content }}</span>
      </template>
    </el-table-column>

    <el-table-column label="操作" width="300">
                    <template #default="scope">
                        <div>
                            <el-popconfirm confirm-button-text="是" cancel-button-text="否" title="您确定删除吗?"
                                icon-color="#626AEF" @confirm="handleDelete(scope.row)">
                                <template #reference>
                                    <el-button>删除</el-button>
                                </template>
                            </el-popconfirm>                           
                        </div>
                    </template>
                </el-table-column>
  </el-table>
  <!-- 分页组件 -->
  <el-pagination
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="pageSizes"
    :page-size="pageSize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
  >
  </el-pagination>

  <!-- 新增对话框 -->
	<el-dialog title="新增" v-model="addVisible" width="30%">
		<el-form label-width="70px">
			<el-form-item label="标题">
				<el-input v-model="noticeForm.title"></el-input>
			</el-form-item>
			<el-form-item label="公告">
				<el-input v-model="noticeForm.content"></el-input>
			</el-form-item>		
		</el-form>
		<template #footer>
			<span class="dialog-footer">
				<el-button @click="addVisible = false">取 消</el-button>
				<el-button type="primary" @click="saveAdd">确 定</el-button>
			</span>
		</template>
	</el-dialog>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive } from "vue";
import { getAllNoticesUrl, getNoticesByPageUrl, deleteNoticeUrl, addNoticeUrl } from "../utils/api";
import { Delete, Edit, Search, Plus } from "@element-plus/icons-vue";
// 声明一个公告类型的接口
interface Notice {
  id: number; // 公告编号
  title: string; // 公告标题
  content: string; // 公告内容
  add_time: string; // 发布时间
  user_id: number; // 用户编号
  user: string; // 用户信息
}
// 公告数据
var tableDataNotices = ref<Notice[]>([]);
// 查询所有的公告并绑定到表格中
// const getAllNoticesData = () => {
//   getAllNoticesUrl().then((res: any) => {
//     console.log(res);
//     tableDataNotices.value = res.data;
//     let total = tableDataNotices.value.length; // 修改总页数
//   });
// };

// 查询所有的公告并绑定到表格中(分页)
const getAllNoticesData = () => {
  let params = {
    currentPage: currentPage.value,
    pageSize: pageSize.value,
  };
  getNoticesByPageUrl(params).then((res: any) => {
    console.log(res);
    tableDataNotices.value = res.data;
    total.value = res.total; // 修改总页数
  });
};

// 页面加载后查询所有公告数据
onMounted(() => {
  getAllNoticesData();
});
// 分页
const pageSizes = [5, 10, 15, 20, 50, 100];
const pageSize = ref(5); // 每页记录条数
const currentPage = ref(1); // 当前页的索引
const small = ref(false);
const background = ref(false);
const disabled = ref(false);
const total = ref(0); // 总页数

// 分页
const handleSizeChange = (val: number) => {
  console.log("${val} items per page");
  pageSize.value = val;
  getAllNoticesData();
};

const handleCurrentChange = (val: number) => {
  console.log("current page: ${val}");
  currentPage.value = val;
  getAllNoticesData();
};

//删除
const handleDelete = (row: Notice) => {
    let params = row.id;
    deleteNoticeUrl(params).then((res) => {
        console.log(res.data.meta);
        getAllNoticesData();
    });
};

// 新增公告
const addVisible = ref(false);  // 是否显示新增公告对话框

let noticeForm = reactive({
	title: "",      // 公告标题
	content: "",    // 公告内容
});

const handleAdd = () => {
	noticeForm.title = ''
	noticeForm.content = ''
	addVisible.value = true;
};

const saveAdd = async () => {
  try {
    let data = {
      title: noticeForm.title,
      content: noticeForm.content,
      user_id: 1, // 用户编号先用个固定值,后面需要得到登录用户的编号
    };  
    const res = await addNoticeUrl(data);
    console.log(res.data);
    dialogFormVisible.value = false;
    getAllNoticesData();
  } catch (error) {
    console.error(error);
  }
};

// const saveAdd = () => {
//   dialogFormVisible.value = false;
//   let data = {
//     title: noticeForm.title,
//     content: noticeForm.content,
//     user_id: 1, // 用户编号先用个固定值,后面需要得到登录用户的编号
//   };
//   console.log(data);
//   addNoticeUrl(data).then((res) => {
//     console.log(res.data);
//     dialogFormVisible.value = false;
//     getAllNoticesData();
//   });
// };
</script>

五、编辑公告 

1. 后端接口(http://127.0.0.1:8000/edit_notice/) 

{
    "id":19,
    "title": "会议通知",
    "content": "abcccccc"
}

2. utils/api.ts中增加函数,用于调用后端接口编辑公告信息

// 编辑公告
export function editNoticeUrl(data:any) {
    return request({
        url: 'api/edit_notice/',
        method: 'put',
        data: data,
    })
}

3.  修改NoticesManagement.vue文件

<template>
  <h1>公告管理</h1>
  <el-row :gutter="20">
    <el-col :span="4">
      <template #default="scope">
        <el-button
          text
          :icon="Edit"
          @click="handleAdd(scope.$index, scope.row)"
          v-permiss="15"
        >
          新增
        </el-button>
      </template>
    </el-col>
  </el-row>
  <el-table ref="tableNoticeRef" :data="tableDataNotices" style="width: 100%">
    <el-table-column prop="id" label="编号" width="180" v-if="true" />
    <el-table-column prop="title" label="标题" width="380">
      <template #default="scope" width="300">
        <span>{{ scope.row.title }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="user" label="发布人姓名" width="100">
      <template #default="scope" width="180">
        <span>{{ scope.row.user }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="content" label="内容" width="280">
      <template #default="scope" width="180">
        <span>{{ scope.row.content }}</span>
      </template>
    </el-table-column>
    <el-table-column label="操作" width="300">
      <template #default="scope">
        <el-button
          text
          :icon="Edit"
          @click="handleEdit(scope.$index, scope.row)"
          v-permiss="15"
        >
          编辑
        </el-button>
        <el-popconfirm
          confirm-button-text="是"
          cancel-button-text="否"
          title="您确定删除吗?"
          icon-color="#626AEF"
          @confirm="handleDelete(scope.row)">
          <template #reference>
            <el-button>删除</el-button>
          </template>
        </el-popconfirm>
      </template>
    </el-table-column>
  </el-table>
  <!-- 分页组件 -->
  <el-pagination
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="pageSizes"
    :page-size="pageSize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
  >
  </el-pagination>

  <!-- 新增对话框 -->
  <el-dialog title="新增" v-model="addVisible" width="30%">
    <el-form label-width="70px">
      <el-form-item label="标题">
        <el-input v-model="noticeForm.title"></el-input>
      </el-form-item>
      <el-form-item label="公告">
        <el-input v-model="noticeForm.content"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="addVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveAdd">确 定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 编辑弹出框 -->
  <el-dialog title="编辑" v-model="editVisible" width="30%">
    <el-form label-width="70px">
      <el-form-item label="编号" v-if="false">
        <el-input v-model="noticeForm.id"></el-input>
      </el-form-item>
      <el-form-item label="标题">
        <el-input v-model="noticeForm.title"></el-input>
      </el-form-item>
      <el-form-item label="内容">
        <el-input v-model="noticeForm.content"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="editVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveEdit">确 定</el-button>
      </span>
    </template>
  </el-dialog>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive } from "vue";
import {
  getAllNoticesUrl,
  getNoticesByPageUrl,
  deleteNoticeUrl,
  addNoticeUrl,
  editNoticeUrl,
} from "../utils/api";
import { Delete, Edit, Search, Plus } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";

// 声明一个公告类型的接口
interface Notice {
  id: number; // 公告编号
  title: string; // 公告标题
  content: string; // 公告内容
  add_time: string; // 发布时间
  user_id: number; // 用户编号
  user: string; // 用户信息
}
// 公告数据
var tableDataNotices = ref<Notice[]>([]);
// 查询所有的公告并绑定到表格中
// const getAllNoticesData = () => {
//   getAllNoticesUrl().then((res: any) => {
//     console.log(res);
//     tableDataNotices.value = res.data;
//     let total = tableDataNotices.value.length; // 修改总页数
//   });
// };

// 查询所有的公告并绑定到表格中(分页)
const getAllNoticesData = () => {
  let params = {
    currentPage: currentPage.value,
    pageSize: pageSize.value,
  };
  getNoticesByPageUrl(params).then((res: any) => {
    console.log(res);
    tableDataNotices.value = res.data;
    total.value = res.total; // 修改总页数
  });
};

// 页面加载后查询所有公告数据
onMounted(() => {
  getAllNoticesData();
});
// 分页
const pageSizes = [5, 10, 15, 20, 50, 100];
const pageSize = ref(5); // 每页记录条数
const currentPage = ref(1); // 当前页的索引
const small = ref(false);
const background = ref(false);
const disabled = ref(false);
const total = ref(0); // 总页数

// 分页
const handleSizeChange = (val: number) => {
  console.log("${val} items per page");
  pageSize.value = val;
  getAllNoticesData();
};

const handleCurrentChange = (val: number) => {
  console.log("current page: ${val}");
  currentPage.value = val;
  getAllNoticesData();
};

//删除
const handleDelete = (row: Notice) => {
  let params = row.id;
  deleteNoticeUrl(params).then((res) => {
    console.log(res.data.meta);
    getAllNoticesData();
  });
};

// 新增公告
const addVisible = ref(false); // 是否显示新增公告对话框

let noticeForm = reactive({
  id: 0,
  title: "", // 公告标题
  content: "", // 公告内容
});

const handleAdd = (index: number, row: any) => {
  noticeForm.title = "";
  noticeForm.content = "";
  addVisible.value = true;
};

const saveAdd = () => {
  addVisible.value = false;
  let data = {
    title: noticeForm.title,
    content: noticeForm.content,
    user_id: 1, // 用户编号先用个固定值,后面需要得到登录用户的编号
  };
  console.log(data);
  addNoticeUrl(data).then((res) => {
    console.log(res.data);
    getAllNoticesData();
  });
};

// 编辑公告
const editVisible = ref(false);
let idx: number = -1;
const handleEdit = (index: number, row: any) => {
  idx = index;
  noticeForm.id = row.id;
  noticeForm.title = row.title;
  noticeForm.content = row.content;
  editVisible.value = true;
};

const saveEdit = async () => {
  try {
    const data = {
      id: noticeForm.id,
      title: noticeForm.title,
      content: noticeForm.content,
    };
    const res = await editNoticeUrl(data);
    console.log(res.data);
    ElMessage.success(`修改第 ${idx + 1} 行成功`);
    editVisible.value = false;
    getAllNoticesData();
  } catch (error) {
    console.error(error);
    // Handle error
  }
};

// const saveEdit = () => {
//   editVisible.value = false;
//   ElMessage.success(`修改第 ${idx + 1} 行成功`);

//   let data = {
//     id: noticeForm.id,
//     title: noticeForm.title,
//     content: noticeForm.content,
//   };
//   console.log(data);
//   editNoticeUrl(data).then((res) => {
//     console.log(res.data);
//     getAllNoticesData();
//   });
// };
</script>

六、筛选公告

​1.  修改NoticesManagement.vue文件

<template>
  <h1>公告管理</h1>
  <el-row :gutter="20">
    <el-col :span="4">
      <template #default="scope">
        <el-button
          text
          :icon="Edit"
          @click="handleAdd(scope.$index, scope.row)"
          v-permiss="15"
        >
          新增
        </el-button>
      </template>
    </el-col>
  </el-row>
  <el-table
    ref="tableNoticeRef"
    :data="
      tableDataNotices.filter(
        (data) =>
          !search ||
          data.title.includes(search) ||
          data.title.toLowerCase().includes(search.toLowerCase())
      )
    "
    style="width: 100%"
    status-icon
  >
    <el-table-column prop="id" label="编号" width="180" v-if="true" />
    <el-table-column prop="title" label="标题" width="380">
      <template #default="scope" width="300">
        <span>{{ scope.row.title }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="user" label="发布人姓名" width="100">
      <template #default="scope" width="180">
        <span>{{ scope.row.user }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="content" label="内容" width="280">
      <template #default="scope" width="180">
        <span>{{ scope.row.content }}</span>
      </template>
    </el-table-column>
    <el-table-column label="操作" width="300">
      <template #header>
        <el-input v-model="search" size="small" placeholder="Type to search" />
      </template>
      <template #default="scope">
        <el-button
          text
          :icon="Edit"
          @click="handleEdit(scope.$index, scope.row)"
          v-permiss="15"
        >
          编辑
        </el-button>
        <el-popconfirm
          confirm-button-text="是"
          cancel-button-text="否"
          title="您确定删除吗?"
          icon-color="#626AEF"
          @confirm="handleDelete(scope.row)"
        >
          <template #reference>
            <el-button>删除</el-button>
          </template>
        </el-popconfirm>
      </template>
    </el-table-column>
  </el-table>
  <!-- 分页组件 -->
  <el-pagination
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="pageSizes"
    :page-size="pageSize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
  >
  </el-pagination>

  <!-- 新增对话框 -->
  <el-dialog title="新增" v-model="addVisible" width="30%">
    <el-form label-width="70px">
      <el-form-item label="标题">
        <el-input v-model="noticeForm.title"></el-input>
      </el-form-item>
      <el-form-item label="公告">
        <el-input v-model="noticeForm.content"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="addVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveAdd">确 定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 编辑弹出框 -->
  <el-dialog title="编辑" v-model="editVisible" width="30%">
    <el-form label-width="70px">
      <el-form-item label="编号" v-if="false">
        <el-input v-model="noticeForm.id"></el-input>
      </el-form-item>
      <el-form-item label="标题">
        <el-input v-model="noticeForm.title"></el-input>
      </el-form-item>
      <el-form-item label="内容">
        <el-input v-model="noticeForm.content"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="editVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveEdit">确 定</el-button>
      </span>
    </template>
  </el-dialog>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive } from "vue";
import {
  getAllNoticesUrl,
  getNoticesByPageUrl,
  deleteNoticeUrl,
  addNoticeUrl,
  editNoticeUrl,
} from "../utils/api";
import { Delete, Edit, Search, Plus } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";

// 声明一个公告类型的接口
interface Notice {
  id: number; // 公告编号
  title: string; // 公告标题
  content: string; // 公告内容
  add_time: string; // 发布时间
  user_id: number; // 用户编号
  user: string; // 用户信息
}
// 公告数据
var tableDataNotices = ref<Notice[]>([]);
// 查询所有的公告并绑定到表格中
// const getAllNoticesData = () => {
//   getAllNoticesUrl().then((res: any) => {
//     console.log(res);
//     tableDataNotices.value = res.data;
//     let total = tableDataNotices.value.length; // 修改总页数
//   });
// };

// 查询所有的公告并绑定到表格中(分页)
const getAllNoticesData = () => {
  let params = {
    currentPage: currentPage.value,
    pageSize: pageSize.value,
  };
  getNoticesByPageUrl(params).then((res: any) => {
    console.log(res);
    tableDataNotices.value = res.data;
    total.value = res.total; // 修改总页数
  });
};

// 页面加载后查询所有公告数据
onMounted(() => {
  getAllNoticesData();
});
// 分页
const pageSizes = [5, 10, 15, 20, 50, 100];
const pageSize = ref(5); // 每页记录条数
const currentPage = ref(1); // 当前页的索引
const small = ref(false);
const background = ref(false);
const disabled = ref(false);
const total = ref(0); // 总页数

// 分页
const handleSizeChange = (val: number) => {
  console.log("${val} items per page");
  pageSize.value = val;
  getAllNoticesData();
};

const handleCurrentChange = (val: number) => {
  console.log("current page: ${val}");
  currentPage.value = val;
  getAllNoticesData();
};

//删除
const handleDelete = (row: Notice) => {
  let params = row.id;
  deleteNoticeUrl(params).then((res) => {
    console.log(res.data.meta);
    getAllNoticesData();
  });
};

// 新增公告
const addVisible = ref(false); // 是否显示新增公告对话框

let noticeForm = reactive({
  id: 0,
  title: "", // 公告标题
  content: "", // 公告内容
});

const handleAdd = (index: number, row: any) => {
  noticeForm.title = "";
  noticeForm.content = "";
  addVisible.value = true;
};

async function saveAdd() {
  try {
    const data = {
      title: noticeForm.title,
      content: noticeForm.content,
      user_id: 1
    }; 
    dialogFormVisible.value = false;
    const res = await addNoticeUrl(data);
    console.log(res.data);
    await getAllNoticesData();
  } catch (error) {
    console.error(error);
  }
}

// const saveAdd = () => {
//   addVisible.value = false;
//   let data = {
//     title: noticeForm.title,
//     content: noticeForm.content,
//     user_id: 1, // 用户编号先用个固定值,后面需要得到登录用户的编号
//   };
//   console.log(data);
//   addNoticeUrl(data).then((res) => {
//     console.log(res.data);
//     getAllNoticesData();
//   });
// };

// 编辑公告
const editVisible = ref(false);
let idx: number = -1;
const handleEdit = (index: number, row: any) => {
  idx = index;
  noticeForm.id = row.id;
  noticeForm.title = row.title;
  noticeForm.content = row.content;
  editVisible.value = true;
};

const saveEdit = () => {
  editVisible.value = false;
  ElMessage.success(`修改第 ${idx + 1} 行成功`);

  let data = {
    id: noticeForm.id,
    title: noticeForm.title,
    content: noticeForm.content,
  };
  console.log(data);
  editNoticeUrl(data).then((res) => {
    console.log(res.data);
    getAllNoticesData();
  });
};

// 筛选数据
const search = ref("");


</script>

七、多选

1.  修改NoticesManagement.vue文件

<template>
  <h1>公告管理</h1>
  <el-row :gutter="20">
    <el-col :span="4">
      <template #default="scope">
        <el-button
          text
          :icon="Edit"
          @click="handleAdd(scope.$index, scope.row)"
          v-permiss="15"
        >
          新增
        </el-button>
      </template>
    </el-col>
  </el-row>
  <el-table
    ref="tableNoticeRef"
    :data="
      tableDataNotices.filter(
        (data) =>
          !search ||
          data.title.includes(search) ||
          data.title.toLowerCase().includes(search.toLowerCase())
      )
    "
    style="width: 100%"
    status-icon
    @selection-change="handleSelectionChange">
    <el-table-column type="selection" width="55" />
    <el-table-column prop="id" label="编号" width="180" v-if="true" />
    <el-table-column prop="title" label="标题" width="380">
      <template #default="scope" width="300">
        <span>{{ scope.row.title }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="user" label="发布人姓名" width="100">
      <template #default="scope" width="180">
        <span>{{ scope.row.user }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="content" label="内容" width="280">
      <template #default="scope" width="180">
        <span>{{ scope.row.content }}</span>
      </template>
    </el-table-column>
    <el-table-column label="操作" width="300">
      <template #header>
        <el-input v-model="search" size="small" placeholder="Type to search" />
      </template>
      <template #default="scope">
        <el-button
          text
          :icon="Edit"
          @click="handleEdit(scope.$index, scope.row)"
          v-permiss="15"
        >
          编辑
        </el-button>
        <el-popconfirm
          confirm-button-text="是"
          cancel-button-text="否"
          title="您确定删除吗?"
          icon-color="#626AEF"
          @confirm="handleDelete(scope.row)"
        >
          <template #reference>
            <el-button>删除</el-button>
          </template>
        </el-popconfirm>
      </template>
    </el-table-column>
  </el-table>
  <!-- 分页组件 -->
  <el-pagination
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="pageSizes"
    :page-size="pageSize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
  >
  </el-pagination>

  <!-- 新增对话框 -->
  <el-dialog title="新增" v-model="addVisible" width="30%">
    <el-form label-width="70px">
      <el-form-item label="标题">
        <el-input v-model="noticeForm.title"></el-input>
      </el-form-item>
      <el-form-item label="公告">
        <el-input v-model="noticeForm.content"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="addVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveAdd">确 定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 编辑弹出框 -->
  <el-dialog title="编辑" v-model="editVisible" width="30%">
    <el-form label-width="70px">
      <el-form-item label="编号" v-if="false">
        <el-input v-model="noticeForm.id"></el-input>
      </el-form-item>
      <el-form-item label="标题">
        <el-input v-model="noticeForm.title"></el-input>
      </el-form-item>
      <el-form-item label="内容">
        <el-input v-model="noticeForm.content"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="editVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveEdit">确 定</el-button>
      </span>
    </template>
  </el-dialog>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive } from "vue";
import {
  getAllNoticesUrl,
  getNoticesByPageUrl,
  deleteNoticeUrl,
  addNoticeUrl,
  editNoticeUrl,
} from "../utils/api";
import { Delete, Edit, Search, Plus } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";

// 声明一个公告类型的接口
interface Notice {
  id: number; // 公告编号
  title: string; // 公告标题
  content: string; // 公告内容
  add_time: string; // 发布时间
  user_id: number; // 用户编号
  user: string; // 用户信息
}
// 公告数据
var tableDataNotices = ref<Notice[]>([]);
// 查询所有的公告并绑定到表格中
// const getAllNoticesData = () => {
//   getAllNoticesUrl().then((res: any) => {
//     console.log(res);
//     tableDataNotices.value = res.data;
//     let total = tableDataNotices.value.length; // 修改总页数
//   });
// };

// 查询所有的公告并绑定到表格中(分页)
const getAllNoticesData = () => {
  let params = {
    currentPage: currentPage.value,
    pageSize: pageSize.value,
  };
  getNoticesByPageUrl(params).then((res: any) => {
    console.log(res);
    tableDataNotices.value = res.data;
    total.value = res.total; // 修改总页数
  });
};

// 页面加载后查询所有公告数据
onMounted(() => {
  getAllNoticesData();
});
// 分页
const pageSizes = [5, 10, 15, 20, 50, 100];
const pageSize = ref(5); // 每页记录条数
const currentPage = ref(1); // 当前页的索引
const small = ref(false);
const background = ref(false);
const disabled = ref(false);
const total = ref(0); // 总页数

// 分页
const handleSizeChange = (val: number) => {
  console.log("${val} items per page");
  pageSize.value = val;
  getAllNoticesData();
};

const handleCurrentChange = (val: number) => {
  console.log("current page: ${val}");
  currentPage.value = val;
  getAllNoticesData();
};

//删除
const handleDelete = (row: Notice) => {
  let params = row.id;
  deleteNoticeUrl(params).then((res) => {
    console.log(res.data.meta);
    getAllNoticesData();
  });
};

// 新增公告
const addVisible = ref(false); // 是否显示新增公告对话框

let noticeForm = reactive({
  id: 0,
  title: "", // 公告标题
  content: "", // 公告内容
});

const handleAdd = (index: number, row: any) => {
  noticeForm.title = "";
  noticeForm.content = "";
  addVisible.value = true;
};

const saveAdd = () => {
  addVisible.value = false;
  let data = {
    title: noticeForm.title,
    content: noticeForm.content,
    user_id: 1, // 用户编号先用个固定值,后面需要得到登录用户的编号
  };
  console.log(data);
  addNoticeUrl(data).then((res) => {
    console.log(res.data);
    getAllNoticesData();
  });
};

// 编辑公告
const editVisible = ref(false);
let idx: number = -1;
const handleEdit = (index: number, row: any) => {
  idx = index;
  noticeForm.id = row.id;
  noticeForm.title = row.title;
  noticeForm.content = row.content;
  editVisible.value = true;
};

const saveEdit = () => {
  editVisible.value = false;
  ElMessage.success(`修改第 ${idx + 1} 行成功`);

  let data = {
    id: noticeForm.id,
    title: noticeForm.title,
    content: noticeForm.content,
  };
  console.log(data);
  editNoticeUrl(data).then((res) => {
    console.log(res.data);
    getAllNoticesData();
  });
};

// 筛选数据
const search = ref("");

// 多选
const multipleSelection = ref<Notice[]>([]);
const handleSelectionChange = (val: Notice[]) => {
    multipleSelection.value = val;
};


</script>

八、全选、清除、批量删除 

1.  修改NoticesManagement.vue文件

<template>
  <h1>公告管理</h1>
  <el-row :gutter="20">
    <el-col :span="4">
      <template #default="scope">
        <el-button
          text
          :icon="Edit"
          @click="handleAdd(scope.$index, scope.row)"
          v-permiss="15"
        >
          新增
        </el-button>
      </template>
    </el-col>
  </el-row>
  <el-table
    ref="tableNoticeRef"
    :data="
      tableDataNotices.filter(
        (data) =>
          !search ||
          data.title.includes(search) ||
          data.title.toLowerCase().includes(search.toLowerCase())
      )
    "
    style="width: 100%"
    status-icon
    @selection-change="handleSelectionChange">
    <el-table-column type="selection" width="55" />
    <el-table-column prop="id" label="编号" width="180" v-if="true" />
    <el-table-column prop="title" label="标题" width="380">
      <template #default="scope" width="300">
        <span>{{ scope.row.title }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="user" label="发布人姓名" width="100">
      <template #default="scope" width="180">
        <span>{{ scope.row.user }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="content" label="内容" width="280">
      <template #default="scope" width="180">
        <span>{{ scope.row.content }}</span>
      </template>
    </el-table-column>
    <el-table-column label="操作" width="300">
      <template #header>
        <el-input v-model="search" size="small" placeholder="Type to search" />
      </template>
      <template #default="scope">
        <el-button
          text
          :icon="Edit"
          @click="handleEdit(scope.$index, scope.row)"
          v-permiss="15"
        >
          编辑
        </el-button>
        <el-popconfirm
          confirm-button-text="是"
          cancel-button-text="否"
          title="您确定删除吗?"
          icon-color="#626AEF"
          @confirm="handleDelete(scope.row)"
        >
          <template #reference>
            <el-button>删除</el-button>
          </template>
        </el-popconfirm>
      </template>
    </el-table-column>
  </el-table>
  <!-- 分页组件 -->
  <el-pagination
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="pageSizes"
    :page-size="pageSize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
  >
  </el-pagination>

  <!-- 新增对话框 -->
  <el-dialog title="新增" v-model="addVisible" width="30%">
    <el-form label-width="70px">
      <el-form-item label="标题">
        <el-input v-model="noticeForm.title"></el-input>
      </el-form-item>
      <el-form-item label="公告">
        <el-input v-model="noticeForm.content"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="addVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveAdd">确 定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 编辑弹出框 -->
  <el-dialog title="编辑" v-model="editVisible" width="30%">
    <el-form label-width="70px">
      <el-form-item label="编号" v-if="false">
        <el-input v-model="noticeForm.id"></el-input>
      </el-form-item>
      <el-form-item label="标题">
        <el-input v-model="noticeForm.title"></el-input>
      </el-form-item>
      <el-form-item label="内容">
        <el-input v-model="noticeForm.content"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="editVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveEdit">确 定</el-button>
      </span>
    </template>
  </el-dialog>
  <div style="margin-top: 20px; margin-left: 20px">
        <el-button @click="toggleSelection(tableDataNotices)">全选</el-button>
        <el-button @click="toggleSelection()">清除</el-button>
        <el-button @click="handleDeleteArray()">批量删除</el-button>
    </div>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive } from "vue";
import {
  getAllNoticesUrl,
  getNoticesByPageUrl,
  deleteNoticeUrl,
  addNoticeUrl,
  editNoticeUrl,
} from "../utils/api";
import { Delete, Edit, Search, Plus } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { ElTable } from "element-plus";

// 声明一个公告类型的接口
interface Notice {
  id: number; // 公告编号
  title: string; // 公告标题
  content: string; // 公告内容
  add_time: string; // 发布时间
  user_id: number; // 用户编号
  user: string; // 用户信息
}
// 公告数据
var tableDataNotices = ref<Notice[]>([]);
// 查询所有的公告并绑定到表格中
// const getAllNoticesData = () => {
//   getAllNoticesUrl().then((res: any) => {
//     console.log(res);
//     tableDataNotices.value = res.data;
//     let total = tableDataNotices.value.length; // 修改总页数
//   });
// };

// 查询所有的公告并绑定到表格中(分页)
const getAllNoticesData = () => {
  let params = {
    currentPage: currentPage.value,
    pageSize: pageSize.value,
  };
  getNoticesByPageUrl(params).then((res: any) => {
    console.log(res);
    tableDataNotices.value = res.data;
    total.value = res.total; // 修改总页数
  });
};

// 页面加载后查询所有公告数据
onMounted(() => {
  getAllNoticesData();
});
// 分页
const pageSizes = [5, 10, 15, 20, 50, 100];
const pageSize = ref(5); // 每页记录条数
const currentPage = ref(1); // 当前页的索引
const small = ref(false);
const background = ref(false);
const disabled = ref(false);
const total = ref(0); // 总页数

// 分页
const handleSizeChange = (val: number) => {
  console.log("${val} items per page");
  pageSize.value = val;
  getAllNoticesData();
};

const handleCurrentChange = (val: number) => {
  console.log("current page: ${val}");
  currentPage.value = val;
  getAllNoticesData();
};

//删除
const handleDelete = (row: Notice) => {
  let params = row.id;
  deleteNoticeUrl(params).then((res) => {
    console.log(res.data.meta);
    getAllNoticesData();
  });
};

// 新增公告
const addVisible = ref(false); // 是否显示新增公告对话框

let noticeForm = reactive({
  id: 0,
  title: "", // 公告标题
  content: "", // 公告内容
});

const handleAdd = (index: number, row: any) => {
  noticeForm.title = "";
  noticeForm.content = "";
  addVisible.value = true;
};

const saveAdd = () => {
  addVisible.value = false;
  let data = {
    title: noticeForm.title,
    content: noticeForm.content,
    user_id: 1, // 用户编号先用个固定值,后面需要得到登录用户的编号
  };
  console.log(data);
  addNoticeUrl(data).then((res) => {
    console.log(res.data);
    getAllNoticesData();
  });
};

// 编辑公告
const editVisible = ref(false);
let idx: number = -1;
const handleEdit = (index: number, row: any) => {
  idx = index;
  noticeForm.id = row.id;
  noticeForm.title = row.title;
  noticeForm.content = row.content;
  editVisible.value = true;
};

const saveEdit = () => {
  editVisible.value = false;
  ElMessage.success(`修改第 ${idx + 1} 行成功`);

  let data = {
    id: noticeForm.id,
    title: noticeForm.title,
    content: noticeForm.content,
  };
  console.log(data);
  editNoticeUrl(data).then((res) => {
    console.log(res.data);
    getAllNoticesData();
  });
};

// 筛选数据
const search = ref("");

// 多选
const multipleSelection = ref<Notice[]>([]);
const tableNoticeRef = ref<InstanceType<typeof ElTable>>();

// 全选和清除按钮
const toggleSelection = (rows?: Notice[]) => {
    if (rows) {
        rows.forEach((row) => {
            tableNoticeRef.value!.toggleRowSelection(row, undefined);
        });
    } else {
        tableNoticeRef.value!.clearSelection();
    }
};

const handleSelectionChange = (val: Notice[]) => {
    multipleSelection.value = val;
};

// 批量删除
const handleDeleteArray = () => {
  for (var i = 0; i < multipleSelection.value.length; i++) {
    let params = multipleSelection.value[i].id;
    deleteNotice(params);
    getAllNoticesData();
  }
  // for (var i = 0; i < multipleSelection.value.length; i++) {
  //       deleteNoticeUrl(multipleSelection.value[i].id).then((res) => {
  //           console.log(res.data.meta);
  //           getAllNoticesData();
  //       });
  //   }
};
</script>

九、Excel导入导出

1. Excel导入

 

2. Excel导出

3. 安装依赖包

npm install xlsx

4.  Excel模板template.xlsx放入public文件夹中

5.   修改NoticesManagement.vue文件

<template>
  <h1>公告管理</h1>
  <el-row :gutter="20">
    <template #default="scope">
      <el-col :span="2">
        <el-button type="primary" @click="exportXlsx">导出Excel</el-button>
      </el-col>
      <el-col :span="2">
        <el-upload
          class="inline-block"
          action="#"
          :limit="1"
          accept=".xlsx, .xls"
          :show-file-list="false"
          :before-upload="beforeUpload"
          :http-request="handleMany"
        >
          <el-button type="primary">批量导入</el-button>
        </el-upload>
      </el-col>
      <el-col :span="2">
        <el-link href="/template.xlsx" type="primary" target="_blank">下载模板</el-link>
      </el-col>
      <el-col :span="2">
        <el-button
          text
          :icon="Edit"
          @click="handleAdd(scope.$index, scope.row)"
          v-permiss="15"
        >
          新增
        </el-button>
      </el-col>
    </template>
  </el-row>
  <el-table
    ref="tableNoticeRef"
    :data="
      tableDataNotices.filter(
        (data) =>
          !search ||
          data.title.includes(search) ||
          data.title.toLowerCase().includes(search.toLowerCase())
      )
    "
    style="width: 100%"
    status-icon
    @selection-change="handleSelectionChange"
  >
    <el-table-column type="selection" width="55" />
    <el-table-column prop="id" label="编号" width="180" v-if="true" />
    <el-table-column prop="title" label="标题" width="380">
      <template #default="scope" width="300">
        <span>{{ scope.row.title }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="user" label="发布人姓名" width="100">
      <template #default="scope" width="180">
        <span>{{ scope.row.user }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="content" label="内容" width="280">
      <template #default="scope" width="180">
        <span>{{ scope.row.content }}</span>
      </template>
    </el-table-column>
    <el-table-column label="操作" width="300">
      <template #header>
        <el-input v-model="search" size="small" placeholder="Type to search" />
      </template>
      <template #default="scope">
        <el-button
          text
          :icon="Edit"
          @click="handleEdit(scope.$index, scope.row)"
          v-permiss="15"
        >
          编辑
        </el-button>
        <el-popconfirm
          confirm-button-text="是"
          cancel-button-text="否"
          title="您确定删除吗?"
          icon-color="#626AEF"
          @confirm="handleDelete(scope.row)"
        >
          <template #reference>
            <el-button>删除</el-button>
          </template>
        </el-popconfirm>
      </template>
    </el-table-column>
  </el-table>
  <!-- 分页组件 -->
  <el-pagination
    @size-change="handleSizeChange"
    @current-change="handleCurrentChange"
    :current-page="currentPage"
    :page-sizes="pageSizes"
    :page-size="pageSize"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
  >
  </el-pagination>

  <!-- 新增对话框 -->
  <el-dialog title="新增" v-model="addVisible" width="30%">
    <el-form label-width="70px">
      <el-form-item label="标题">
        <el-input v-model="noticeForm.title"></el-input>
      </el-form-item>
      <el-form-item label="公告">
        <el-input v-model="noticeForm.content"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="addVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveAdd">确 定</el-button>
      </span>
    </template>
  </el-dialog>

  <!-- 编辑弹出框 -->
  <el-dialog title="编辑" v-model="editVisible" width="30%">
    <el-form label-width="70px">
      <el-form-item label="编号" v-if="false">
        <el-input v-model="noticeForm.id"></el-input>
      </el-form-item>
      <el-form-item label="标题">
        <el-input v-model="noticeForm.title"></el-input>
      </el-form-item>
      <el-form-item label="内容">
        <el-input v-model="noticeForm.content"></el-input>
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="editVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveEdit">确 定</el-button>
      </span>
    </template>
  </el-dialog>
  <div style="margin-top: 20px; margin-left: 20px">
    <el-button @click="toggleSelection(tableDataNotices)">全选</el-button>
    <el-button @click="toggleSelection()">清除</el-button>
    <el-button @click="handleDeleteArray()">批量删除</el-button>
  </div>
</template>
<script setup lang="ts">
import { ref, onMounted, reactive } from "vue";
import {
  getAllNoticesUrl,
  getNoticesByPageUrl,
  deleteNoticeUrl,
  addNoticeUrl,
  editNoticeUrl,
} from "../utils/api";
import { Delete, Edit, Search, Plus } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { ElTable } from "element-plus";
import * as XLSX from "xlsx";
import { UploadProps } from "element-plus";

// 声明一个公告类型的接口
interface Notice {
  id: number; // 公告编号
  title: string; // 公告标题
  content: string; // 公告内容
  add_time: string; // 发布时间
  user_id: number; // 用户编号
  user: string; // 用户信息
}
// 公告数据
var tableDataNotices = ref<Notice[]>([]);
// 查询所有的公告并绑定到表格中
// const getAllNoticesData = () => {
//   getAllNoticesUrl().then((res: any) => {
//     console.log(res);
//     tableDataNotices.value = res.data;
//     let total = tableDataNotices.value.length; // 修改总页数
//   });
// };

// 查询所有的公告并绑定到表格中(分页)
const getAllNoticesData = async () => {
  let params = {
    currentPage: currentPage.value,
    pageSize: pageSize.value,
  };
  await getNoticesByPageUrl(params).then((res: any) => {
    console.log(res);
    tableDataNotices.value = res.data;
    total.value = res.total; // 修改总页数
  });
};

// 页面加载后查询所有公告数据
onMounted(() => {
  getAllNoticesData();
});
// 分页
const pageSizes = [5, 10, 15, 20, 50, 100];
const pageSize = ref(5); // 每页记录条数
const currentPage = ref(1); // 当前页的索引
const small = ref(false);
const background = ref(false);
const disabled = ref(false);
const total = ref(0); // 总页数

// 分页
const handleSizeChange = (val: number) => {
  console.log("${val} items per page");
  pageSize.value = val;
  getAllNoticesData();
};

const handleCurrentChange = (val: number) => {
  console.log("current page: ${val}");
  currentPage.value = val;
  getAllNoticesData();
};

//删除
const handleDelete = async (row: Notice) => {
  let params = row.id;
  await deleteNoticeUrl(params).then((res) => {
    console.log(res.data.meta);
    getAllNoticesData();
  });
};

// 新增公告
const addVisible = ref(false); // 是否显示新增公告对话框

let noticeForm = reactive({
  id: 0,
  title: "", // 公告标题
  content: "", // 公告内容
});

const handleAdd = (index: number, row: any) => {
  noticeForm.title = "";
  noticeForm.content = "";
  addVisible.value = true;
};

const saveAdd = async () => {
  addVisible.value = false;
  let data = {
    title: noticeForm.title,
    content: noticeForm.content,
    user_id: 1, // 用户编号先用个固定值,后面需要得到登录用户的编号
  };
  console.log(data);
  await addNoticeUrl(data).then((res) => {
    console.log(res.data);
    getAllNoticesData();
  });
};

// 编辑公告
const editVisible = ref(false);
let idx: number = -1;
const handleEdit = (index: number, row: any) => {
  idx = index;
  noticeForm.id = row.id;
  noticeForm.title = row.title;
  noticeForm.content = row.content;
  editVisible.value = true;
};

const saveEdit = async () => {
  editVisible.value = false;
  ElMessage.success(`修改第 ${idx + 1} 行成功`);

  let data = {
    id: noticeForm.id,
    title: noticeForm.title,
    content: noticeForm.content,
  };
  console.log(data);
  await editNoticeUrl(data).then((res) => {
    console.log(res.data);
    getAllNoticesData();
  });
};

// 筛选数据
const search = ref("");

// 多选
const multipleSelection = ref<Notice[]>([]);
const tableNoticeRef = ref<InstanceType<typeof ElTable>>();

// 全选和清除按钮
const toggleSelection = (rows?: Notice[]) => {
  if (rows) {
    rows.forEach((row) => {
      tableNoticeRef.value!.toggleRowSelection(row, undefined);
    });
  } else {
    tableNoticeRef.value!.clearSelection();
  }
};

const handleSelectionChange = (val: Notice[]) => {
  multipleSelection.value = val;
};

// 批量删除
const handleDeleteArray = async () => {
  // console.log(multipleSelection.value)
  for (var i = 0; i < multipleSelection.value.length; i++) {
    await deleteNoticeUrl(multipleSelection.value[i].id).then((res) => {
      console.log(res.data.meta);
      getAllNoticesData();
    });
  }
};

// Excel导入导出
// 导出Excel函数
const exportXlsx = () => {
  // 使用computed属性计算表格数据,只有在tableDataNotices变化时才会重新计算
  const list = computed(() => {
    // 将tableDataNotices数组转换为二维数组
    return [["编号", "标题", "内容", "发布时间", "发布人姓名"], ...tableDataNotices.value.map((item: any, i: number) => {
      // 返回一个数组,包含该条记录的所有字段
      return [i + 1, item.title, item.content, item.add_time, item.user];
    })];
  }).value;

  // 将数据转换为工作表
  let WorkSheet = XLSX.utils.aoa_to_sheet(list);
  // 创建一个新的工作簿
  let new_workbook = XLSX.utils.book_new();
  // 将工作表添加到工作簿中,并指定名称为“第一页”
  XLSX.utils.book_append_sheet(new_workbook, WorkSheet, "第一页");
  // 保存工作簿为Excel文件,文件名为“表格.xlsx”
  XLSX.writeFile(new_workbook, `表格.xlsx`);
};


// 导入Excel
const importList = ref<any>([]);
// 上传前对Excel文件进行解析
const beforeUpload: UploadProps["beforeUpload"] = async (rawFile) => {
  // 调用analysisExcel函数,解析Excel文件并将结果保存在importList中
  importList.value = await analysisExcel(rawFile);
  // 返回true表示上传文件
  return true;
};

// 解析Excel文件
const analysisExcel = (file: any) => {
  return new Promise(function (resolve, reject) {
    const reader = new FileReader();
    reader.onload = function (e: any) {
      const data = e.target.result;
      // 使用XLSX读取二进制数据并将其转换为json格式
      const workbook = XLSX.read(data, { type: "binary" });
      // 获取第一个Sheet的名称
      const sheetName = workbook.SheetNames[0];
      // 将Sheet转换为json格式
      const result = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]);
      resolve(result);
    };
    reader.readAsBinaryString(file);
  });
};

// 批量添加公告
const handleMany = async () => {
  // 将importList中的数据转换为公告列表
  const notices = importList.value.map((item: any) => ({
    title: item["标题"],
    content: item["内容"],
    user_id: 1,
  }));

  // 添加公告并刷新页面
  for (let i = 0; i < notices.length; i++) {
    await addNoticeUrl(notices[i]);
  }
  location.reload();
};
</script>
 
  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Python+Vue+Django前后端分离项目实战,涉及到使用Python语言编写后端服务,使用Vue框架构建前端界面,并通过Django框架作为API接口实现前后端数据交互的方式。在实战项目中也会涉及到数据库设计和调用、权限控制、文件上传等问题的解决。 ### 回答2: Python、VueDjango是现在非常流行的前后端开发技术。如果你想学习这些技术,那么前后端分离是一个很好的选择。在这个项目中使用Python作为后端编程语言,Django作为Web框架,Vue作为前端框架。我们可以在这个项目中学习到很多关于前后端分离的经验。 首先,前后端分离可以让我们更好地组织我们的代码。在一个分离的项目中,我们可以通过明确的接口来分离前端和后端。这样一来,我们可以专注于开发代码,而不必担心前后端之间的交互问题。 其次,前后端分离可以使我们更好地实现可重用性。在这个项目中,我们可以编写可重用的Vue组件,并在不同的前端页面中使用它们。同样地,我们也可以编写可重用的Django应用程序,并在不同的后端端点中使用它们。这会使我们的代码更加清晰简洁,也可以提高我们的开发效率。 最后,前后端分离可以让我们更好地实现可维护性。在一个分离的项目中,我们可以更轻松地进行单元测试和端到端测试。这可以帮助我们保持代码的质量,并尽早发现和解决潜在的问题。 总之,Python、VueDjango前后端分离项目是一个非常好的学习项目。通过这个项目,我们可以从实践中学习如何使用这些技术,并在以后的项目中更好地应用它们。 ### 回答3: Python、VueDjango是目前非常流行的技术栈之一,其中Python和Django主要用于后端开发,Vue则是一款流行的前端框架。Python和Django的优点在于它们易于学习、可扩展性强、社区活跃,并且可以用于构建各种类型的Web应用程序。而Vue的优点在于它简洁、高效、组件化,并且可以很好地配合其他框架和库使用。 前后端分离是一种可以将前端和后端分别开发的方法,这种方法具有很多优点。首先,可以使开发人员更加专注于各自的领域,减少互相干扰和影响。其次,这种方法可以提高应用程序的可维护性和可扩展性。最后,这种方法还可以提高开发效率,使开发人员能够更加高效地开发应用程序。 在前后端分离项目实战中,需要注意以下几点。首先,需要确定应用程序的需求,确定前端和后端的接口规范。其次,需要使用合适的工具和框架来完成前后端的开发任务。对于后端开发,可以使用Django的REST框架,这个框架可以很快地构建RESTful API,并且配合数据库使用。而对于前端开发,则可以使用Vue框架来开发,Vue可以很好地处理数据和UI逻辑。最后,需要着重测试和调试应用程序,确保应用程序的正确性和可用性。 总的来说,Python、VueDjango是一组非常流行的技术栈,非常适合用于前后端分离项目的开发。在开发前需要确定好需求,选择好工具和框架,开发期间需要注重测试和调试,这样才能开发出高质量的应用程序。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值