SpringCloud+Vue3一个字段多个存储以及回显

♥️作者:小宋1021
🤵‍♂️个人主页:小宋1021主页
♥️坚持分析平时学习到的项目以及学习到的软件开发知识,和大家一起努力呀!!!
🎈🎈加油! 加油! 加油! 加油
🎈欢迎评论 💬点赞👍🏻 收藏 📂加关注+!


目录

场景:

存储过程:

数据库:

后端:

实体类:

CourseManageSaveReqVO:

CourseManageRespVO:

Mapper:

CourseManageServiceImpl实现类:

回显过程:

前端:

主要方法:

列表项:

全部代码:


场景:

新发布一个补课班的班级课程,班级上课的科目不一定是一个有可能是多个,这就需要一个字段存储多条数据,主要的修改都在实现类里,下面我们来看怎样实现。

数据库存储结果:

存储过程:

数据库:

按照自己的字段需求定义即可,我定义的是varchar

后端:

实体类:

多定义一个subject2[]字段是为了前端传值的时候好拼接,留着以后有用,存储的时候只需要一个String[]类型的subject字段即可。

    /**
     * 科目
     */
    private String subject;
    /**
     * 科目2
     */
    private String[] subject2;

CourseManageSaveReqVO:

同样是String[]类型的数组,为了存储。

 @Schema(description = "科目")
    private String[] subject;

CourseManageRespVO:

在控制回显的VO里也要回显subject2,前端需要拼接

    @Schema(description = "科目")
    @ExcelProperty("科目")
    private String subject;

    @Schema(description = "科目2")
    @ExcelProperty("科目2")
    private String[] subject2;

Mapper:

直接继承BaseMapperX方法即可。

/**
 * 课程管理 Mapper
 *
 * @author 平台管理员
 */
@Mapper
public interface CourseManageMapper extends BaseMapperX<CourseManageDO> {

}

Service层:

/**
 * 课程管理 Service 接口
 *
 * @author 平台管理员
 */
public interface CourseManageService {

    /**
     * 创建课程管理
     *
     * @param createReqVO 创建信息
     * @return 编号
     */
    Long createCourseManage(@Valid CourseManageSaveReqVO createReqVO);



}

CourseManageServiceImpl实现类:

/**
 * 课程管理 Service 实现类
 *
 * @author 平台管理员
 */
@Service
@Validated
public class CourseManageServiceImpl implements CourseManageService {

    @Resource
    private CourseManageMapper courseManageMapper;

    @Override
    @LogRecord(type = TEACH_COURSE_MANAGE_TYPE, subType = TEACH_COURSE_MANAGE_SUB_TYPE, bizNo = "{{#teachCourseManage.id}}",
            success = TEACH_COURSE_MANAGE_CREATE_SUCCESS)
    public Long createCourseManage(CourseManageSaveReqVO createReqVO) {
        // 插入
        CourseManageDO courseManage = BeanUtils.toBean(createReqVO, CourseManageDO.class);
        String[] subjects = createReqVO.getSubject();
        courseManage.setSubject(String.join(",", subjects));
        courseManageMapper.insert(courseManage);

        // 3. 记录操作日志上下文
        LogRecordContext.putVariable("teachCourseManage", courseManage);

        // 返回
        return courseManage.getId();
    }

    @Override
    @LogRecord(type = TEACH_COURSE_MANAGE_TYPE, subType = TEACH_COURSE_MANAGE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
            success = TEACH_COURSE_MANAGE_UPDATE_SUCCESS)
    public void updateCourseManage(CourseManageSaveReqVO updateReqVO) {
        // 校验存在
        validateCourseManageExists(updateReqVO.getId());

        CourseManageDO oldCourseManage = courseManageMapper.selectById(updateReqVO.getId());

        // 更新
        CourseManageDO updateObj = BeanUtils.toBean(updateReqVO, CourseManageDO.class);
        courseManageMapper.updateById(updateObj);

        // 3. 记录操作日志上下文
        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCourseManage, CourseManageSaveReqVO.class));
        LogRecordContext.putVariable("teachCourseManage", oldCourseManage);

    }

}

下面我们来拆解一下新增方法:

 CourseManageDO courseManage = BeanUtils.toBean(createReqVO, CourseManageDO.class);

这句话的作用是:

BeanUtils.toBean(createReqVO, CourseManageDO.class); 这行代码是将一个对象(createReqVO)的属性值复制到另一个对象(CourseManageDO的一个实例)的相应属性中。这个过程通常被称为“属性拷贝”或“Bean转换”。

这里的createReqVO是一个请求对象(Request Value Object),比如来自Web请求的表单数据或JSON数据经过反序列化后得到的对象。而CourseManageDO(Data Object)则是一个用于数据库操作或业务逻辑处理的数据对象。

 String[] subjects = createReqVO.getSubject();

定义了一个名叫subjects的String类型的数据,来获取createReqVO传过来的subject的值。

 courseManage.setSubject(String.join(",", subjects));

给courseManage实体类使用set方法赋值,并使用String.join方法拼接,这就使数据库存储的数据是2,1,0

courseManageMapper.insert(courseManage);

使用BaseMapperX的方法直接插入。

到这存储过程就结束了,要注意的是实体类的类型要保持一致,要是数组类型。

前端:

 <el-form-item label="科目" prop="subject">
        <el-select v-model="formData.subject" 
        multiple
        placeholder="请选择科目">
          <el-option
            v-for="dict in getIntDictOptions(DICT_TYPE.SUBJECT)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>

const formData = ref({
  id: undefined,
  courseName: undefined,
  courseType: undefined,
  chargeMethod: undefined,
  priceStandard: undefined,
  courseStatus: undefined,
  grade: undefined,
  subject: [],
  term: undefined,
  studentName: undefined,
  studentPhone: undefined,
  courseSource: undefined,
  courseApplicationScope: undefined,
  remark: undefined,
  deduceClassRules: undefined,
  operaName: undefined,
  operaTime: undefined,
  operaType: undefined,
  operaExplain: undefined,
  coursePrice: undefined,
  courseStudyTime: undefined,
  discount: undefined,
  giftCourseNumber: undefined,

})

回显过程:

前端:

我这里有一些是测试数据,有些数据没有填写完全,请大家忽略,只关注”科目“即可。

主要方法:

/** 查询列表 */
const getList = async () => {
  loading.value = true
  try {
    const data = await CourseManageApi.getCourseManagePage(queryParams)
    list.value = data.list
    total.value = data.total
    const subjectList = []
    const subjectList2 = []
    subjectList.value = getIntDictOptions(DICT_TYPE.SUBJECT)
    list.value.forEach((item) => {
      if (item.subject) {
        item.subject2 = []
        subjectList2.value = item.subject.split(',')
        subjectList.value.forEach(i => {
          subjectList2.value.forEach(e => {
            if (Number(e) === i.value) {
              console.log(item.subject2, typeof (item.subject2), 'asdsad')
              item.subject2.push(i.label)
            }
          })
        })
      }

    })

  } finally {
    loading.value = false
  }
}

    const subjectList = []
    const subjectList2 = []

这里定义了两个数组subjectList 用来接收后端传过来的subject的值,也就是存在数据库里的值,

subjectList2 用来去数据字典里查找匹配再进行回显

subjectList.value = getIntDictOptions(DICT_TYPE.SUBJECT)

把数据库存的值和数据字典里的值匹配再存到subjectList里

getIntDictOptions方法:

export const getIntDictOptions = (dictType: string): NumberDictDataType[] => {
  // 获得通用的 DictDataType 列表
  const dictOptions: DictDataType[] = getDictOptions(dictType)
  // 转换成 number 类型的 NumberDictDataType 类型
  // why 需要特殊转换:避免 IDEA 在 v-for="dict in getIntDictOptions(...)" 时,el-option 的 key 会告警
  const dictOption: NumberDictDataType[] = []
  dictOptions.forEach((dict: DictDataType) => {
    dictOption.push({
      ...dict,
      value: parseInt(dict.value + '')
    })
  })
  return dictOption
}

  list.value.forEach((item) => {
      if (item.subject) {
        item.subject2 = []
        subjectList2.value = item.subject.split(',')
        subjectList.value.forEach(i => {
          subjectList2.value.forEach(e => {
            if (Number(e) === i.value) {
              item.subject2.push(i.label)
            }
          })
        })
      }

    })

  }

这里用了两个forEach循环,item的箭头函数是vue3特有的语法,目的就是遍历传过来的值再与数据字典里的值一一匹配,匹配成功以后再通过push方法插入到subject2[]这个数组中,通过subject2进行回显

列表项:

 <el-table-column label="科目" align="center" prop="subject2" show-overflow-tooltip="true">

          <template #default="scope">
            <el-tag v-for="(item, index) in scope.row.subject2" style="margin-right: 5px" :key="index" size="small">
              {{ item }}
            </el-tag>
          </template>
        </el-table-column>

用el-tag和v-for遍历显示subject2数组中的每一个值,margin-right: 5px是为了每个科目之间有间距,show-overflow-tooltip="true"是隐藏显示, {{ item }}是插值表达式,插入到列表里。

全部代码:

<template>
  <div>
    <ContentWrap>
      <!-- 搜索工作栏 -->
      <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
        <el-form-item label="学员姓名" prop="studentName">
          <el-input v-model="queryParams.studentName" placeholder="请输入学员姓名" clearable @keyup.enter="handleQuery"
            class="!w-240px" />
        </el-form-item>
        <el-form-item label="手机号" prop="studentPhone">
          <el-input v-model="queryParams.studentPhone" placeholder="请输入手机号" clearable @keyup.enter="handleQuery"
            class="!w-240px" />
        </el-form-item>
        <el-form-item label="课程来源" prop="courseSource">
          <el-select v-model="queryParams.courseSource" placeholder="请选择课程来源" clearable class="!w-240px">
            <el-option v-for="dict in getIntDictOptions(DICT_TYPE.COURSE_SOURCE)" :key="dict.value" :label="dict.label"
              :value="dict.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="课程类型" prop="courseType">
          <el-select v-model="queryParams.courseType" placeholder="请选择课程类型" clearable class="!w-240px">
            <el-option v-for="dict in getIntDictOptions(DICT_TYPE.COURSE_TYPE)" :key="dict.value" :label="dict.label"
              :value="dict.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="年级" prop="grade">
          <el-select v-model="queryParams.grade" placeholder="请选择年级" clearable class="!w-240px">
            <el-option v-for="dict in getIntDictOptions(DICT_TYPE.GRADE)" :key="dict.value" :label="dict.label"
              :value="dict.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="科目" prop="subject">
          <el-select v-model="queryParams.subject" placeholder="请选择科目" clearable class="!w-240px">
            <el-option v-for="dict in getIntDictOptions(DICT_TYPE.SUBJECT)" :key="dict.value" :label="dict.label"
              :value="dict.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="学期" prop="term">
          <el-select v-model="queryParams.term" placeholder="请选择学期" clearable class="!w-240px">
            <el-option v-for="dict in getIntDictOptions(DICT_TYPE.TERM)" :key="dict.value" :label="dict.label"
              :value="dict.value" />
          </el-select>
        </el-form-item>


        <el-form-item>
          <el-button @click="handleQuery">
            <Icon icon="ep:search" class="mr-5px" /> 搜索
          </el-button>
          <el-button @click="resetQuery">
            <Icon icon="ep:refresh" class="mr-5px" /> 重置
          </el-button>
          <el-button type="primary" plain @click="openForm('create')" v-hasPermi="['teach:course-manage:create']">
            <Icon icon="ep:plus" class="mr-5px" /> 新增
          </el-button>
        </el-form-item>
      </el-form>
    </ContentWrap>

    <!-- 列表 -->
    <ContentWrap>
      <el-table v-loading="loading" :data="list" :stripe="true">
        <el-table-column label="序号" type="index" header-align="center" align="center" width="60px" fixed />
        <el-table-column label="课程名称" align="center" prop="courseName" width="150px" />
        <el-table-column label="课程来源" align="center" prop="courseSource">
          <template #default="scope">
            <dict-tag :type="DICT_TYPE.COURSE_SOURCE" :value="scope.row.courseSource" />
          </template>
        </el-table-column>
        <el-table-column label="课程类型" align="center" prop="courseType">
          <template #default="scope">
            <dict-tag :type="DICT_TYPE.COURSE_TYPE" :value="scope.row.courseType" />
          </template>
        </el-table-column>
        <el-table-column label="收费方式" align="center" prop="chargeMethod">
          <template #default="scope">
            <dict-tag :type="DICT_TYPE.CHARGE_METHOD" :value="scope.row.chargeMethod" />
          </template>
        </el-table-column>
        <el-table-column label="定价标准" align="center" prop="priceStandard" />
        <el-table-column label="课程状态" align="center" prop="courseStatus">
          <template #default="scope">
            <dict-tag :type="DICT_TYPE.COURSE_STATUS" :value="scope.row.courseStatus" />
          </template>
        </el-table-column>
        <el-table-column label="年级" align="center" prop="grade" width="150px">
          <template #default="scope">
            <dict-tag :type="DICT_TYPE.GRADE" :value="scope.row.grade" />
          </template>
        </el-table-column>
        <el-table-column label="科目" align="center" prop="subject2" show-overflow-tooltip="true">

          <template #default="scope">
            <el-tag v-for="(item, index) in scope.row.subject2" style="margin-right: 5px" :key="index" size="small">
              {{ item }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="学期" align="center" prop="term">
          <template #default="scope">
            <dict-tag :type="DICT_TYPE.TERM" :value="scope.row.term" />
          </template>
        </el-table-column>
        <el-table-column label="创建人" align="center" prop="creator">
          <template #default="scope">
            {{ userList.find((user) => user.id === scope.row.creator)?.nickname }}
          </template>
        </el-table-column>
        <el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="180px" />
        <el-table-column label="操作" align="center" fixed="right" width="200px">
          <template #default="scope">
            <el-button link type="primary" @click="openForm('update', scope.row.id)"
              v-hasPermi="['teach:course-manage:update']">
              编辑
            </el-button>
            <el-button link type="primary" @click="details('update', scope.row.id)" v-hasPermi="['study:plan:delete']">
              详情
            </el-button>
            <el-button link type="primary" @click="openForm('update', scope.row.id)"
              v-hasPermi="['teach:course-manage:update']">
              启用
            </el-button>
            <el-button link type="danger" @click="handleDelete(scope.row.id)"
              v-hasPermi="['teach:course-manage:delete']">
              停用
            </el-button>
            <!-- <el-button
            link
            type="danger"
            @click="handleDelete(scope.row.id)"
            v-hasPermi="['teach:course-manage:delete']"
          >
            删除
          </el-button> -->
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页 -->
      <Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
        @pagination="getList" />
    </ContentWrap>
  </div>
  <!-- 表单弹窗:添加/修改 -->
  <CourseManageForm ref="formRef" @success="getList" />
  <!-- 表单弹窗:详情 -->
  <el-drawer v-model="drawer" title="详情" :direction="direction" v-if="drawer" size="71%" class="drawer"
    destory-on-close>
    <DetailForm ref="detailRef" :detailId="detailId" />
  </el-drawer>

</template>

<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE, getStrDictOptions } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { CourseManageApi, CourseManageVO } from '@/api/teach/coursemanage'
import DetailForm from '@/views/teach/coursemanagePlus/Index.vue'
import CourseManageForm from './CourseManageForm.vue'
import type { DrawerProps } from 'element-plus'
import { ref } from 'vue';
import * as UserApi from '@/api/system/user'
const userList = ref<UserApi.UserVO[]>([])

/** 课程管理 列表 */
defineOptions({ name: 'CourseManage' })

const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
const direction = ref<DrawerProps['direction']>('rtl')
const loading = ref(true) // 列表的加载中
const list = ref<CourseManageVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  courseType: undefined,
  grade: undefined,
  subject: undefined,
  term: undefined,
  studentName: undefined,
  studentPhone: undefined,
  courseSource: undefined,
})
const queryFormRef = ref() // 搜索的表单

/** 查询列表 */
const getList = async () => {
  loading.value = true
  try {
    const data = await CourseManageApi.getCourseManagePage(queryParams)
    list.value = data.list
    total.value = data.total
    const subjectList = []
    const subjectList2 = []
    subjectList.value = getIntDictOptions(DICT_TYPE.SUBJECT)
    list.value.forEach((item) => {
      if (item.subject) {
        item.subject2 = []
        subjectList2.value = item.subject.split(',')
        subjectList.value.forEach(i => {
          subjectList2.value.forEach(e => {
            if (Number(e) === i.value) {
              console.log(item.subject2, typeof (item.subject2), 'asdsad')
              item.subject2.push(i.label)
            }
          })
        })
      }

    })

  } finally {
    loading.value = false
  }
}

/** 搜索按钮操作 */
const handleQuery = () => {
  queryParams.pageNo = 1
  getList()
}
/** 查看详情 */
const detailRef = ref()
const drawer = ref(false)
const detailId = ref()
const details = (type: string, id?: number) => {
  drawer.value = true
  detailId.value = id
}



/** 重置按钮操作 */
const resetQuery = () => {
  queryFormRef.value.resetFields()
  handleQuery()
}

/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
  formRef.value.open(type, id)
}

/** 删除按钮操作 */
const handleDelete = async (id: number) => {
  try {
    // 删除的二次确认
    await message.delConfirm()
    // 发起删除
    await CourseManageApi.deleteCourseManage(id)
    message.success(t('common.delSuccess'))
    // 刷新列表
    await getList()
  } catch { }
}


/** 初始化 **/
onMounted(async () => {
  getList()
  userList.value = await UserApi.getSimpleUserList()
})
</script>
<style scoped lang="scss">
.drawer {
  width: 70% !important;
}

:deep(.el-table .cell) {
  overflow: visible;
}
</style>

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值