效果图

api.js

import axios from "axios";
//创建一个axios实例
let api = axios.create({
    baseURL: "/api",
    timeout: 3000
});
​
export default api;

vue开发模板

<template>
  <!-- 搜索条件 -->
  <div class="search">
    <el-form :model="searchForm" inline ref="searchRef">
      <el-form-item label="编号:" prop="id">
        <el-input v-model="searchForm.id" placeholder="请输入编号" />
      </el-form-item>
      <el-form-item label="名称:" prop="name">
        <el-input v-model="searchForm.name" placeholder="请输入名称" />
      </el-form-item>
      <el-form-item label="时间:" prop="time">
        <el-date-picker v-model="searchForm.time" value-format="YYYY-MM-DD" type="daterange" unlink-panels
          range-separator="到" start-placeholder="开始时间" end-placeholder="截至时间" />
      </el-form-item>
      <el-form-item label="分类:" prop="sort">
        <el-select name="sort" id="sort" style="width: 140px" v-model="searchForm.sort" placeholder="请选择分类">
          <el-option label="不限" value="" />
          <el-option v-for="item in sortList" :key="item.id" :label="item.name" :value="item.id"
            :disabled="item.disabled" />
        </el-select>
      </el-form-item>
    </el-form>
  </div>
​
  <!-- 操作区域 -->
  <div class="action" style="display: flex; align-items: center; justify-content: space-between;">
    <div>
      <el-button type="primary" :icon="Search" solid @click="search()">查询</el-button>
      <el-button type="success" :icon="CirclePlus" @click="add" solid>添加</el-button>
      <el-button type="warning" :icon="Edit" @click="edit" solid>编辑</el-button>
      <el-button type="danger" :icon="Delete" @click="remove" solid>删除</el-button>
      <el-button type="info" :icon="Refresh" @click="reset" solid>重置</el-button>
    </div>
    <el-radio-group v-model="viewType" size="small">
      <el-radio-button label="formView">
        <div class="radio-content">
          <el-icon>
            <Grid />
          </el-icon>
          <span>卡片视图</span>
        </div>
      </el-radio-button>
      <el-radio-button label="tblView">
        <div class="radio-content">
          <el-icon>
            <Plus />
          </el-icon>
          <span>表格视图</span>
        </div>
      </el-radio-button>
    </el-radio-group>
  </div>
​
​
  <!-- 显示区域 -->
  <div class="grid" v-show="viewType === 'formView'">
    <el-table :data="tblDate" border @row-click="tblRowClick" ref="tblRef" :row-class-name="tblRowClassName">
      <el-table-column type="selection" width="55" align="center" fixed />
      <el-table-column label="头像" fixed width="100">
        <template #default="scope">
          <div :style="'background-image: url(' + (baseUrl + scope.row.avatar) + ')'"></div>
        </template>
      </el-table-column>
      <el-table-column label="编号" prop="id" />
      <el-table-column label="操作" width="160" align="center" fixed="right">
        <template #default="scope">
          <el-button type="primary" size="small" @click.stop="editRow(scope.row)">编辑</el-button>
          <el-button type="danger" size="small" @click.stop="removeRow(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
​
​
  <div class="card" v-show="viewType === 'tblView'">
    <div class="card-container">
      <el-card shadow="hover" class="data-card" v-for="item in tblDate" :key="item.id">
        <template #header>
          <div class="card-header">
            <div class="card-title-section">
              <el-checkbox v-model="item.name"></el-checkbox>
              <span class="card-title">{{ item.name }}</span>
            </div>
            <div class="card-actions">
              <el-button @click="editRow(item)" type="text">编辑</el-button>
              <span class="divider">|</span>
              <el-button @click="removeRow(item)" type="text" class="card-remove">删除</el-button>
            </div>
          </div>
        </template>
        <el-form :model="item" label-position="left" label-width="50px">
          <el-form-item label="编号:">
            <el-input v-model="item.id" readonly />
          </el-form-item>
          <el-form-item label="名称:">
            <el-input v-model="item.name" readonly />
          </el-form-item>
          <el-form-item label="分类">
            <div style="display: flex; gap: 10px; flex-wrap: wrap;">
              <el-tag v-for="(sort, index) in item.sort" :key="index">
                {{ sort }}
              </el-tag>
            </div>
          </el-form-item>
        </el-form>
      </el-card>
    </div>
  </div>
​
​
​
  <!-- 分页区域 -->
  <div class="pagination">
    <el-pagination v-model:current-page="pi.currentPage" v-model:page-size="pi.pageSize" ref="piDRef"
      layout="total, prev, pager, next" :total="pi.total" @change="search" />
  </div>
  <!-- 对话框 -->
  <div class="dialog">
    <el-dialog v-model="dlgVisible" :title="dlgName" width="30%" align-center draggable @close="resetDlg">
      <el-form ref="dlgTblRef" :model="dlgTblForm" label-width="80px" :rules>
        <el-row>
          <el-col :span="16">
            <el-form-item label="编号" prop="id">
              <el-input v-model="dlgTblForm.id" placeholder="请输入编号"></el-input>
            </el-form-item>
            <el-form-item label="名称" prop="name">
              <el-input v-model="dlgTblForm.name" placeholder="请输入名称"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-upload class="avatar" action="/avatar" :on-success="uploadSuccess" :show-file-list="false"
              :headers="headers">
              <div class="img" v-if="dlgTblForm.avatar" :style="'background-image: url(' + (dlgTblForm.avatar) + ')'">
              </div>
              <el-icon v-else class="icon">
                <Plus />
              </el-icon>
            </el-upload>
          </el-col>
        </el-row>
        <el-form-item label="描述" prop="description">
          <el-input type="textarea" v-model="dlgTblForm.description" :rows="4" placeholder="请输入描述" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dlgVisible = false">取消</el-button>
          <el-button type="primary" @click="doSubmit()">确定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { onMounted, ref, reactive, toRaw } from 'vue';
import { Search, CirclePlus, Edit, Delete, Refresh, Plus, Grid } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus';
import api from '@/util/api'
onMounted(() => {
  //初始化操作
  // search()
  // searchSort()
})
//===============================================视图===============================
let viewType = ref('formView')
function tblRowClassName({ row, rowIndex }) {
  switch (row.status) {
    case 0:
      return 'danger-row';
    case 1:
      return 'warning-row';
    case 2:
      return 'success-row';
    default:
      return '';
  }
}
//===============================================查询相关===============================
//搜索条件
let searchForm = ref({
  id: null,
  time: null,
  sort: null,
})
//单选框数据
let sortList = ref([])
//表格数据
let tblDate = ref()
tblDate.value = [
  { id: 1, name: 'n1', sort: ['s1', 's2', 's3'], status: 1 },
  { id: 2, name: 'n2', sort: ['s1', 's2', 's3'], status: 0 },
  { id: 3, name: 'n3', sort: ['s1', 's2', 's3'], status: 1 },
  { id: 4, name: 'n4', sort: ['s1', 's2', 's3'], status: 2 },
]
//分页信息
let pi = ref({
  currentPage: 1,
  pageSize: 5,
  total: 10,
})
//条件查询
async function search(currentPage = 1, pageSize = 10) {
  let searchBean = toRaw(searchForm)
  if (searchBean.time) {
    searchBean.beginTime = searchBean.time[0]
    searchBean.endTime = searchBean.time[0]
    delete searchBean.time
  }
  let resp = await api({
    url: "/list",
    method: "get",
    params: {
      currentPage,
      pageSize,
      ...searchForm
    }
  })
  if (resp.success) {
    tblDate.value = resp.data
    pi.total.value = resp.data.total
  } else {
    ElMessage.error(resp.msg)
  }
}
//种类查询 
async function searchSort() {
  let resp = await api({
    url: "/sortList",
    method: "get",
    params: {
​
    }
  })
  if (resp.success) {
    sortList.value = resp.data.records
    pi.currentPage = resp.data.current
    pi.pageSize = resp.data.size
    pi.total = resp.data.total
  } else {
    ElMessage.error(resp.msg)
  }
}
//重置查询条件
function reset() {
  searchForm.value.resetFields();
}
//===================================================选中================================
//行响应对象
let tblRef = ref()
//行选中/取消
function tblRowClick(row) {
  tblRef.value.toggleRowSelection(row)
}
//===================================================删除=================================
//操作区删除
function remove() {
  let rows = tblRef.value.getSelectionRows();
  if (rows.length === 0) {
    ElMessage.warning("请选中数据后进行操作!");
  } else {
    ElMessageBox.confirm("是否删除当前选中的数据", "警告", {
      cancelButtonText: "取消",
      confirmButtonText: "确定",
      type: "warning"
    }).then(() => {
      let ids = rows.map(it => it.id);
      removeByIds(ids);
    }).catch(() => {
      ElMessage.success("取消删除");
    })
  }
}
//行信息删除
function removeRow(row) {
  ElMessageBox.confirm("是否删除当前选中的数据", "警告", {
    cancelButtonText: "取消",
    confirmButtonText: "确定",
    type: "warning"
  }).then(() => {
    let ids = toRaw(row).id
    removeByIds([ids]);
  }).catch(() => {
    ElMessage.success("取消删除");
  })
}
//实际删除
async function removeByIds(ids) {
  let resp = await api({
    url: "/delete",
    method: "delete",
    data: ids,
  })
  if (resp.success) {
    console.log(resp)
    ElMessage.success(resp.msg)
  } else {
    ElMessage.error(resp.msg || ("删除数据失败,请重新尝试"));
  }
  search(pi.currentPage, pi.pageSize);
}
//====================================================添加/编辑==========================
//对话框是否显示
let dlgVisible = ref(false)
//对话框标题
let dlgName = ref('对话框标题')
//对话框表单
let dlgTblForm = ref({
  id: null,
  name: null,
  avatar: null,
  description: null,
})
//显示添加对话框
function add() {
  dlgName.value = "添加数据"
  dlgVisible.value = true;
}
//显示编辑对话框 + 数据回显
function edit() {
  dlgName.value = "编辑数据"
  let editRow = tblRef.value.getSelectionRows();
  if (editRow.length === 0) {
    ElMessage.warning("请选中您要修改的行");
  } else if (editRow.length !== 1) {
    ElMessage.warning("您仅能选中一条数据");
  } else {
    dlgVisible.value = true;
    nextTick(() => {
      dlgTblForm.value = cloneDeep(toRaw(editRow[0]));
    })
  }
}
function editRow(row) {
  dlgName.value = "编辑数据";
  dlgVisible.value = true;
  nextTick(() => {
    depTblForm.value = cloneDeep(toRaw(row));
  })
}
//点击提交
function doSubmit() {
  if (dlgName.value === "添加数据") {
    submitAdd()
  } else if (dlgName.value === "编辑数据") {
    submitEdit()
  }
}
//添加数据
async function submitAdd() {
  let formInfo = toRaw(dlgTblForm.value)
  let resp = await api({
    url: "/add",
    method: "post",
    data: {
      ...formInfo
    }
  })
  if (resp.success) {
    dlgVisible.value = false
    ElMessage.success(resp.msg)
    dlgTblForm.value.resetFields();
    search(pi.currentPage, pi.pageSize)
  } else {
    ElMessage.error(resp.msg)
  }
}
//添加数据
async function submitEdit() {
  let formInfo = toRaw(dlgTblForm.value)
  let resp = await api({
    url: "/edit",
    method: "post",
    data: {
      ...formInfo
    }
  })
  if (resp.success) {
    dlgVisible.value = false
    ElMessage.success(resp.msg)
    dlgTblForm.value.resetFields();
    search(pi.currentPage, pi.pageSize)
  } else {
    ElMessage.error(resp.msg)
  }
}
//===================================================图片上传===============================
import baseUrl from "@/util/constant.js"
import { getJwt } from "@/api/jwt.js";
//设置返回头信息
const headers = {
  "Authorization": getJwt()
}
function uploadSuccess(resp) {
  let url = baseUrl + resp.data;
  dlgTblForm.value.avatar = url;
}
​
​
​
​
</script>
<style>
.el-table .warning-row {
  background-color: #fff9e6;
}
​
.el-table .danger-row {
  background-color: #ffeeea;
}
​
.el-table .success-row {
  background-color: #f0f9ff;
}
</style>
<style scoped>
/* ==================================视图=========================== */
.radio-content {
  display: flex;
  align-items: center;
  gap: 4px;
}
​
​
​
/* =================================卡片============================== */
.card-container {
  display: flex;
  flex-wrap: wrap;
  gap: 2%;
}
​
.data-card {
  flex: 0 1 calc(32.9% - 1%);
  margin-bottom: 20px;
}
​
.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
​
.card-title-section {
  display: flex;
  align-items: center;
  gap: 10px;
}
​
.card-remove {
  color: #F56C6C;
}
​
.divider {
  color: #dcdfe6;
  margin: 0 8px;
}
​
/* ===================================图片============================== */
.avatar {
  width: 80px;
  height: 80px;
  border: 1px dashed #ccc;
  border-radius: 4px;
  margin-left: 8px;
  display: flex;
}
​
.avatar .icon {
  font-size: 28px;
  justify-content: center;
  align-items: center;
}
​
.avatar .img {
  width: 80px;
  height: 80px;
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center center;
}
</style>
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐