第4章 系统管理员模块功能实现

4.1 新增功能实现

4.1.1 在controller目录下新建AdminController类

代码如下所示:

package cn.xueden.controller;

import cn.xueden.service.IAdminService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**功能描述:系统管理员模块前端控制器
 * @author:梁志杰
 * @date:2022/5/6
 * @description:cn.xueden.controller
 * @version:1.0
 */
@RestController
@RequestMapping("admin")
public class AdminController {
    
    private final IAdminService adminService;

    public AdminController(IAdminService adminService) {
        this.adminService = adminService;
    }
}

4.1.2 在AdminController类下添加一个add方法

代码如下所示:

 /**
     * 新增记录
     * @param admin
     * @return
     */
    @PostMapping
    public BaseResult add(@RequestBody Admin admin){
        adminService.add(admin);
        return BaseResult.success("新增成功");
    }

4.1.3 在IAdminService接口下添加add方法

代码如下所示:

      /**
     * 新增记录
     * @param admin
     */
    void add(Admin admin);

4.1.4 在AdminServiceImpl接口实现类下添加add方法

代码如下所示:

/**
     * 新增记录
     * @param member
     */
    @Override
   @Transactional(rollbackFor = Exception.class)
    public void add(Member member) {
        memberRepository.save(member);
    }

4.1.5 列表页面布局

步骤01 创建文件夹admin,如图所示:

在这里插入图片描述

步骤02 在admin文件夹下创建一个名为index.vue的文件,如图所示:

在这里插入图片描述

步骤03 输入如下代码进行页面布局

<template>
<div>
<!--搜索框 start-->
  <div class="search__example--wrap">
  </div>
<!--搜索框 end-->
<!--操作按钮 start-->
  <div class="button__example--wrap">
     <el-button type="primary" icon="el-icon-circle-plus-outline">新增</el-button>
    <el-button type="danger" icon="el-icon-delete">批量删除</el-button>
  </div>
<!--操作按钮 end-->
<!--表格 start-->
<com-table>

</com-table>
<!--表格 end-->
<!--弹出层 start-->
<com-dialog>
</com-dialog>
<!--弹出层 end-->
        
 </div>
</template>

步骤04 修改如下代码

<script>
export default {
  name: 'Index'
}
</script>

把以上代码修改为:

<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
  components: {

  },
  setup() {

  }
})
</script>

步骤05 修改路由地址

修改src->router->index.ts文件,修改asyncRouterMap对象,代码如下所示:

export const asyncRouterMap: AppRouteRecordRaw[] = [
  {
    path: '/sys',
    component: Layout,
    redirect: '/sys/filestore',
    name: 'FileStore',
    meta: {
      title: '系统设置',
      icon: 'guide',
      alwaysShow: true
    },
    children: [
      {
        path: 'filestore',
        component: () => import('_v/filestore/index.vue'),
        name: 'FileStore',
        meta: {
          icon: 'cloud-storage',
          title: '自定义存储'
        }
      },
      {
        path: 'galleryclassify',
        component: () => import('_v/galleryclassify/index.vue'),
        name: 'GalleryClassify',
        meta: {
          icon: 'gallery-classify',
          title: '图库分类'
        }
      },
      {
        path: 'fileresource',
        component: () => import('_v/fileresource/index.vue'),
        name: 'FileResource',
        meta: {
          icon: 'pdf',
          title: '上传文件管理'
        }
      },
      {
        path: 'wxpay',
        component: () => import('_v/wxpay/index.vue'),
        name: 'WxPay',
        meta: {
          icon: 'wxpay',
          title: '微信支付'
        }
      },
      {
        path: 'banner',
        component: () => import('_v/banner/index.vue'),
        name: 'banner',
        meta: {
          icon: 'example',
          title: 'Banner管理'
        }
      }
    ]
  },
  {
    path: '/wechat',
    component: Layout,
    redirect: '/wechat/appletinfo',
    name: 'AppletInfo',
    meta: {
      title: '微信设置',
      icon: 'wechat',
      alwaysShow: true
    },
    children: [
      {
        path: 'appletinfo',
        component: () => import('_v/appletinfo/index.vue'),
        name: 'AppletInfo',
        meta: {
          icon: 'applet-info',
          title: '小程序管理'
        }
      }]
  },
  {
    path: '/member',
    component: Layout,
    redirect: '/member/index',
    name: 'Member',
    meta: {
      title: '用户管理',
      icon: 'peoples',
      alwaysShow: true
    },
    children: [
      {
        path: 'index',
        component: () => import('_v/member/index.vue'),
        name: 'Member',
        meta: {
          icon: 'people',
          title: '用户列表'
        }
      }, {
        path: 'admin',
        component: () => import('_v/admin/index.vue'),
        name: 'Admin',
        meta: {
          icon: 'people',
          title: '系统管理员列表'
        }
      }]
  }
]


4.1.6 添加和修改页面功能实现

步骤01 在admin目录下新建一个components文件夹,并在此文件夹下创建一个InfoWrite.vue页面,如图所示:

在这里插入图片描述

步骤02 在InfoWrite.vue页面,添加如下代码进行布局:

<template>
  <div>
    <el-form
        ref="formRef"
        :model="form"
        :rules="rules"
        label-width="100px"
    >
      <el-row>
        <el-col :span="24">
          <el-form-item prop="loginName" label="登录账号">
            <el-input v-model="form.loginName" placeholder="请输入登录账号" />
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item prop="password" label="登录密码">
            <el-input v-model="form.password" placeholder="请输入登录密码" />
          </el-form-item>
        </el-col>
        <el-col :span="24">
          <el-form-item prop="status" label="状态">
            <el-select v-model="form.status" placeholder="请选择状态" style="width: 100%;">
              <el-option v-for="item in statusOptions" :label="item.label" :value="item.value" />
            </el-select>
          </el-form-item>
        </el-col>

        <el-col :span="24">
          <el-form-item prop="remarks" label="备注">
            <el-input v-model="form.remarks" type="textarea" placeholder="请输入备注" />
          </el-form-item>
        </el-col>

      </el-row>
    </el-form>
    <div class="dialong__button--wrap">
      <el-button @click="close">取消</el-button>
      <el-button :loading="subLoading" type="primary" @click="setListData">保存</el-button>
    </div>
  </div>
</template>


步骤03 修改如下代码:

<script>
export default {
  name: "InfoWrite"
}
</script>

为:

<script lang="ts">
import { defineComponent, PropType, reactive, unref, ref } from 'vue'
import { Message } from '_c/Message'
export default defineComponent({
  name: 'InfoWrite',
  props: {
    info: {
      type: Object as PropType<any>,
      default: () => null
    }
  },
  emits: ['close', 'success'],
  setup(props, { emit }) {
    // 表单对象
    const formRef = ref<HTMLElement | null>(null)
    // 加载对象
    const subLoading = ref<boolean>(false)
    // 定义状态下拉选择项
    const statusOptions = ref<object[]>([{
      label: '启用',
      value: 1
    }, {
      label: '禁用',
      value: 0
    }])

    return {
      formRef,
      subLoading,
      statusOptions

    }
  }
})
</script>

步骤04 定义校验规则提示,代码如下所示:

const requiredRule = {
  required: true,
  message: '该项为必填项'
}

步骤05 定义一个表单对象,代码如下所示:

// 定义表单对象
    const form = reactive<InfoWriteParams>({
      id: 0,
      loginName: '',
      password: '',
      status: 0,
      remarks: ''
    })

步骤06 定义校验规则,代码如下所示:

// 定义表单字段规则,哪些必填,哪些可以不填
    const rules = reactive<InfoWriteRules>({
      loginName: [requiredRule],
      status: [requiredRule],
      password: [requiredRule]
    })

步骤07 在components目录下,创建一个types.ts文件,在里面添加一个参数接口、规则接口等,代码如下所示:

// 设置字段数据类型
export interface InfoWriteParams {
    id?: number,
    loginName: string,
    password: string,
    status: number,
    remarks: string
}
// 定义校验规则
export interface InfoWriteRules {
    loginName?: any[],
    password?: any[],
    status?: any[],
    remarks?: any[]
}


步骤08 编写提交表单的函数,包括新增和编辑,代码如下所示:

 // 提交表单的函数
    function setListData() {
      const formRefWrap = unref(formRef as any)
      try {
        subLoading.value = true
        formRefWrap.validate(async(valid:boolean) => {
          if (valid) {
            const formData = unref(form)
            const res = await addApi({
              data: formData
            })

            if (res) {
              Message.success(form.id ? '编辑成功' : '添加成功')
              emit('success', form.id ? 'edit' : 'add')
            }
          } else {
            console.log('error submit!!')
            return false
          }
        })
      } catch (err) {
        console.log(err)
      } finally {
        subLoading.value = false
      }
    }


步骤9 编写一个关闭表单的函数

// 关闭表单
    function close() {
      emit('close')
    }

步骤10 修改return对象,代码如下所示:

 return {
      formRef,
      subLoading,
      statusOptions,
      form,
      rules,
      setListData,
      close
    }

步骤11 编写调用后端接口的API,

在admin目录下新增一个名为api.ts的文件,主要编写一个是提交表单的接口函数,代码如下所示:

import { fetch } from '@/axios-config/axios'

// 参数接口
interface PropsData {
    params?: any,
    data?: any
}

// 提交表单接口函数
export const addApi = ({ data }: PropsData): any => {
  return fetch({ url: 'member', method: 'post', data })
}


步骤12 在index.vue添加弹出层组件,代码如下所示:

 <!--弹出层 start-->
  <com-dialog v-model="dialogVisible" :title="title">
    <info-write v-if="comName==='InfoWrite'" :info="info" @close="toggleVisible" @success="success" />
  </com-dialog>
<!--弹出层 end-->

添加comName、toggleVisible、currentChange到useExample() 和return{},代码如下所示

setup() {
    const info = ref<any>(null)
    const { dialogVisible, comName,title,currentChange,
      toggleVisible } = useExample()

    return {
      info,
      dialogVisible,
      comName,
      toggleVisible
    }
  }

导入相关依赖,代码如下所示:

import { defineComponent, ref } from 'vue'
import InfoWrite from './components/InfoWrite.vue'
import { useExample } from '@/hooks/useExample'
import { Message } from '_c/Message'

添加组件,代码如下所示:

 components: {
    InfoWrite
  },

步骤13 编写一个提交表单成功后的回调函数

// 提交表单成功后的回调函数
    function success(type: string) {
      if (type === 'add') {
        currentChange(1)
      }
      toggleVisible()
    }

注意:需要把这个函数放入到return返回对象里面

步骤14 编写一个打开弹出框的函数,代码如下所示:

// 打开弹窗
    function open(row: any, component: string) {
      comName.value = component
      title.value = !row ? '新增' : (component === 'Detail' ? '详情' : '编辑')
      info.value = row || null
      toggleVisible(true)
    }

注意:需要把这个函数放入到return返回对象里面

给新增按钮添加一个点击事件,代码如下所示:

 <!--操作按钮 start-->
  <div class="button__example--wrap">
    <el-button type="primary" icon="el-icon-circle-plus-outline" @click="open(false,'InfoWrite')">新增</el-button>
    <el-button type="danger" icon="el-icon-delete">批量删除</el-button>
  </div>
  <!--操作按钮 end-->

步骤15 修改return返回对象,代码如下所示:

  return {
      info,
      dialogVisible,
      comName,
      toggleVisible,
      title,
      success,
      open
    }

步骤16 修改axios-config目录下的axios.ts文件及store目录下的app.ts文件

axios.ts文件代码加入如下代码:

    headers: {
      'Content-Type': headersType || default_headers,
      'Authorization': wsCache.get(appStore.loginToken)
    }

app.ts文件加入如下代码:

 public loginToken = 'loginToken' // 登录后的token

步骤17 修改login目录下的Index文件,添加如下代码到login函数即可

 // 保存登录token
wsCache.set(appStore.loginToken, res.result)

4.1.7 自动填充创建者功能实现

步骤01 自定义注解EnableXuedenCreateBy,代码如下所示:

package cn.xueden.annotation;

import cn.xueden.annotation.generation.CreationCreateByGeneration;
import org.hibernate.annotations.ValueGenerationType;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**功能描述:自动填充创建者ID
 * @author:梁志杰
 * @date:2022/4/11
 * @description:cn.xueden.annotation
 * @version:1.0
 */
@ValueGenerationType(
        generatedBy = CreationCreateByGeneration.class
)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface EnableXuedenCreateBy {
}


步骤02 新建一个名为CreationCreateByGeneration的类,代码如下所示:

package cn.xueden.annotation.generation;

import cn.xueden.annotation.EnableXuedenCreateBy;
import org.hibernate.tuple.AnnotationValueGeneration;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGenerator;

/**功能描述:创建者ID生成器
 * @author:梁志杰
 * @date:2022/4/11
 * @description:cn.xueden.annotation.generation
 * @version:1.0
 */
public class CreationCreateByGeneration implements AnnotationValueGeneration<EnableXuedenCreateBy> {
    private ValueGenerator<?> generator;
    public CreationCreateByGeneration() {

    }

    @Override
    public void initialize(EnableXuedenCreateBy enableXuedenCreateBy, Class<?> propertyType) {
        this.generator = CreateByGenerators.get(propertyType);
    }

    @Override
    public GenerationTiming getGenerationTiming() {
        return GenerationTiming.INSERT;
    }

    @Override
    public ValueGenerator<?> getValueGenerator() {
      return this.generator;
    }

    @Override
    public boolean referenceColumnInSql() {
        return false;
    }

    @Override
    public String getDatabaseGeneratedReferencedColumnValue() {
        return null;
    }
}


步骤03 新建一个名为CreateByGenerators的类,点如下所示:

package cn.xueden.annotation.generation;


import cn.xueden.utils.HutoolJWTUtil;
import org.hibernate.tuple.ValueGenerator;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

import java.util.*;

/**
 * @author:梁志杰
 * @date:2022/4/11
 * @description:cn.xueden.annotation.generation
 * @version:1.0
 */
final class CreateByGenerators {
    private static final Map<Class<?>, ValueGenerator<?>> generators = new HashMap();

    public CreateByGenerators() {
    }

    public static ValueGenerator<?> get(Class<?> type) {
        ValueGenerator<?> valueGeneratorSupplier = (ValueGenerator)generators.get(type);
        if (Objects.isNull(valueGeneratorSupplier)) {
            return null;
        } else {
            return valueGeneratorSupplier;
        }
    }
    static {
        generators.put(java.lang.Long.class, (session, owner) -> {
            // 在此实现业务逻辑获取数据
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String token = (String)request.getServletContext().getAttribute("token");
            Long creatBy = HutoolJWTUtil.parseToken(token);
            return creatBy;
        });
    }
}


步骤04 修改BaseEntity类,代码如下所示:

    /**
     * 创建者ID
     */
    @Column(name = "create_by")
    @EnableXuedenCreateBy
    private Long createBy;

4.1.8 自动填充更新者功能实现

步骤01 自定义注解EnableXuedenUpdateBy,代码如下所示:

package cn.xueden.annotation;


import cn.xueden.annotation.generation.CreationUpdateByGeneration;
import org.hibernate.annotations.ValueGenerationType;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**功能描述:自动填充更新者ID
 * @author:梁志杰
 * @date:2022/4/11
 * @description:cn.xueden.annotation
 * @version:1.0
 */
@ValueGenerationType(
        generatedBy = CreationUpdateByGeneration.class
)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface EnableXuedenUpdateBy {
}


步骤02 新建一个名为CreationUpdateByGeneration的类,代码如下所示:

package cn.xueden.annotation.generation;

import cn.xueden.annotation.EnableXuedenUpdateBy;
import org.hibernate.tuple.AnnotationValueGeneration;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGenerator;

/**
 * @author:梁志杰
 * @date:2022/4/12
 * @description:cn.xueden.annotation.generation
 * @version:1.0
 */
public class CreationUpdateByGeneration implements AnnotationValueGeneration<EnableXuedenUpdateBy> {
    private ValueGenerator<?> generator;

    public CreationUpdateByGeneration() {

    }

    @Override
    public void initialize(EnableXuedenUpdateBy enableXuedenUpdateBy, Class<?> propertyType) {
        this.generator = UpdateByGenerators.get(propertyType);
    }

    @Override
    public GenerationTiming getGenerationTiming() {
        return GenerationTiming.ALWAYS;
    }

    @Override
    public ValueGenerator<?> getValueGenerator() {
        return this.generator;
    }

    @Override
    public boolean referenceColumnInSql() {
        return false;
    }

    @Override
    public String getDatabaseGeneratedReferencedColumnValue() {
        return null;
    }
}


步骤03 新建一个名为UpdateByGenerators的类,点如下所示:

package cn.xueden.annotation.generation;

import cn.xueden.utils.HutoolJWTUtil;
import org.hibernate.tuple.ValueGenerator;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author:梁志杰
 * @date:2022/4/11
 * @description:cn.xueden.annotation.generation
 * @version:1.0
 */
final class UpdateByGenerators {
    private static final Map<Class<?>, ValueGenerator<?>> generators = new HashMap();

    public UpdateByGenerators() {
    }

    public static ValueGenerator<?> get(Class<?> type) {
        ValueGenerator<?> valueGeneratorSupplier = (ValueGenerator)generators.get(type);
        if (Objects.isNull(valueGeneratorSupplier)) {
            return null;
            // throw new HibernateException("Unsupported property type [" + type.getName() + "] for @EnableXuedenCreateBy or @EnableXuedenUpdateBy generator annotation");
        } else {
            return valueGeneratorSupplier;
        }
    }
    static {
        generators.put(java.lang.Long.class, (session, owner) -> {
            // 在此实现业务逻辑获取数据
            Long updateBy = 2L;
            if(RequestContextHolder.getRequestAttributes()!=null){
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                String token = (String)request.getServletContext().getAttribute("token");
                updateBy = HutoolJWTUtil.parseToken(token);
            }
            return updateBy;
        });
    }
}


步骤04 修改BaseEntity类,代码如下所示:

 /**
     * 更新者ID
     */
    @Column(name = "update_by")
    @EnableXuedenUpdateBy
    private Long updateBy;

4.2 获取列表功能实现

4.2.1 新增表格列表columns对象

// 表格列表名称
    const columns = ref<any[]>([
      {
        field: 'index',
        type: 'index',
        label: '序号',
        width: 60,
        index: (index: number) => {
          return (defalutParams.pageIndex - 1) * defalutParams.pageSize + index + 1
        }
      },
      {
        field: 'loginName',
        label: '登录账号',
        showOverflowTooltip: true
      },
      {
        field: 'password',
        label: '登录密码',
        showOverflowTooltip: true
      },
      {
        field: 'status',
        label: '状态',
        slots: {
          default: 'status'
        }
      },
      {
        field: 'createTime',
        label: '创建时间',
        formatter: (row: any, column: any, cellValue: any, index: number) => {
          return formatTime(row.createTime, 'yyyy-MM-dd')
        },
        showOverflowTooltip: true
      },
      {
        field: 'updateTime',
        label: '更新时间',
        formatter: (row: any, column: any, cellValue: any, index: number) => {
          return formatTime(row.updateTime, 'yyyy-MM-dd')
        },
        showOverflowTooltip: true
      },
      {
        field: 'remarks',
        label: '备注',
        showOverflowTooltip: true
      }

    ])


4.2.2 修改表格

代码如下所示:

  <!--表格 start-->
  <com-table v-loading="loading" :columns="columns" selection :data="tableData">
    <!--状态-->
    <template #status="scope">
      <el-tag
        :type="scope.row.status === 0
          ? 'danger'
          : (scope.row.status === 1
            ? 'warning'
            : 'success')"
      >{{ scope.row.status === 0
        ? '禁用'
        : (scope.row.status === 1
          ? '启用'
          : '未知') }}
      </el-tag>
    </template>

  </com-table>
  <!--表格 end-->

4.2.3 修改useExample()函数

代码如下所示:

const { dialogVisible, comName, title, defalutParams,loading,tableData,total,
      toggleVisible, currentChange } = useExample()

4.2.4 修改return返回对象

代码如下所示:

  return {
      info,
      dialogVisible,
      comName,
      toggleVisible,
      title,
      success,
      open,
      columns,
      loading,
      tableData,
      total
    }

4.2.5 编写获取列表数据函数

代码如下所示:

 // 请求列表数据
    async function getList(data?: any): Promise<void> {
      try {
        const res = await getListApi({
          params: Object.assign(defalutParams, data || {})
        })

        total.value = res.totalElements
        tableData.value = res.content
      } finally {
        loading.value = false
      }
    }
    getList()

4.2.6 编写调用后端接口的API

在api.ts文件下新增一个名为getListApi的函数,代码如下所示:

// 获取列表接口
export const getListApi = ({ params }: PropsData): any => {
  return fetch({ url: '/galleryClassify', method: 'get', params })
}

4.2.7 在AdminController类下添加getList方法

代码如下所示:

 /**
     * 带查询参数的分页方法
     * @param queryCriteria 查询条件
     * @param pageVo 分页参数
     * @return
     */
    @GetMapping
    public ResponseEntity<Object> getList(AdminQueryCriteria queryCriteria, PageVo pageVo){
        Pageable pageable = PageRequest.of(pageVo.getPageIndex()-1,pageVo.getPageSize(), Sort.Direction.DESC, "id");
        return new ResponseEntity<>(adminService.getList(queryCriteria,pageable), HttpStatus.OK);
    }

4.2.8 在IAdminService接口添加getList方法

代码如下所示:

   /**
     * 带查询参数的分页方法
     * @param queryCriteria
     * @param pageable
     * @return
     */
    Object getList(AdminQueryCriteria queryCriteria, Pageable pageable);

4.2.9 在AdminServiceImpl接口实现类添加getList方法

代码如下所示:

/**
     * 带查询参数的分页方法
     * @param queryCriteria
     * @param pageable
     * @return
     */
    @Override
    public Object getList(AdminQueryCriteria queryCriteria, Pageable pageable) {
        Page<Admin> page = adminRepository.findAll((root, query, criteriaBuilder) -> QueryHelp.getPredicate(root,queryCriteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page);
    }

11.3.10 编写一个查询条件类AdminQueryCriteria

代码如下所示:

package cn.xueden.service.dto;

import cn.xueden.annotation.EnableXuedenQuery;
import lombok.Data;

/**功能描述:系统管理员查询条件
 * @author:梁志杰
 * @date:2022/5/8
 * @description:cn.xueden.service.dto
 * @version:1.0
 */
@Data
public class AdminQueryCriteria {
    /**
     * 登录账号
     */
    @EnableXuedenQuery(blurry="loginName")
    private String loginName;
    /**
     * 状态
     */
    @EnableXuedenQuery()
    private String status;
}





4.3 分页功能实现

4.3.1 修改表格

代码如下所示:

 <!--表格 start-->
    <com-table v-loading="loading" :columns="columns" selection :data="tableData"
     :pagination="{
        currentPage: defalutParams.pageIndex,
        total: total,
        onSizeChange: handleSizeChange,
        onCurrentChange: handleCurrentChange
      }"
       @selection-change="handleSelectionChange">
      <!--状态-->
      <template #status="scope">
        <el-tag
          :type="scope.row.status === 0
            ? 'danger'
            : (scope.row.status === 1
              ? 'warning'
              : 'success')"
        >{{ scope.row.status === 0
          ? '禁用'
          : (scope.row.status === 1
            ? '启用'
            : '未知') }}
        </el-tag>
      </template>

    </com-table>
    <!--表格 end-->

4.3.2 新增改变展示条数的handleSizeChange函数

代码如下所示:

 // 展示多少条
    function handleSizeChange(val: number) {
      // 该方法重置了一些默认参数
      sizeChange(val)
      getList()
    }

4.3.3 新增跳转页码handleCurrentChange函数

代码如下所示:

 // 展示第几页
    function handleCurrentChange(val: number) {
      // 该方法重置了一些默认参数
      currentChange(val)
      getList()
    }

4.3.4 修改useExample()函数

代码如下所示:

const { dialogVisible, comName, title, defalutParams, loading, tableData, total,sizeChange,
       handleSelectionChange,toggleVisible, currentChange } = useExample()

4.3.5 修改return返回对象

代码如下所示:

return {
      info,
      dialogVisible,
      comName,
      toggleVisible,
      title,
      success,
      open,
      columns,
      loading,
      tableData,
      total,
      defalutParams,
      handleSelectionChange,
      handleSizeChange,
      handleCurrentChange
    }

4.4 查询列表功能实现

4.4.1 在index.vue文件中添加搜索框布局

代码如下所示:

 <!--搜索框 start-->
  <div class="search__example--wrap">
    <com-search :data = "searchData" @search-submit="searchSubmit" @reset-submit="resetSubmit"/>
  </div>
  <!--搜索框 end-->

4.4.2 添加搜索对象

代码如下所示:

// 搜索框字段
const searchData = [{
  label: '手机号',
  value: '',
  itemType: 'input',
  field: 'loginName',
  placeholder: '请输入登录账号',
  clearable: true
}, {
  label: '状态',
  value: '',
  itemType: 'select',
  field: 'status',
  options: [{
    title: '禁用',
    value: 0
  }, {
    title: '启用',
    value: 1
  }]
}]

4.4.3 添加搜索函数和重置函数

代码如下所示:

 // 查询
    function searchSubmit(data: any) {
      // 该方法重置了一些默认参数
      currentChange(1)
      getList(data)
    }

    // 重置
    function resetSubmit(data: any) {
      // 该方法重置了一些默认参数
      currentChange(1)
      getList(data)
    }

4.4.4 修改return返回对象

代码如下所示:

return {
      info,
      dialogVisible,
      comName,
      toggleVisible,
      title,
      success,
      open,
      columns,
      loading,
      tableData,
      total,
      defalutParams,
      handleSelectionChange,
      handleSizeChange,
      handleCurrentChange,
      searchData,
      searchSubmit,
      resetSubmit
    }

4.5 查询详情功能实现

4.5.1 在table表格中添加查看详情的按钮

代码如下所示:

<!--表格按钮-->
      <template #action="scope">
        <el-button type="primary" size="mini" @click="open(scope.row,'InfoWrite')">编辑</el-button>
      </template>

4.5.2 修改columns对象

在后面加入如下代码:

{
        field: 'action',
        label: '操作',
        width: '220px',
        slots: {
          default: 'action'
        }
      }

4.5.3 在InfoWrite.vue文件中添加getDet()函数

代码如下所示:

 // 获取详情信息
    async function getDet() {
      if (props.info) {
        const id = (props.info as any).id
        try {
          const res = await getDetApi({
            params: {
              id: id
            }
          })
          if (res.status === 200) {
            for (const key in form) {
              form[key] = res.result[key]
            }
          }
        } catch (e) {
          console.log(e)
        }
      }
    }
    getDet()

4.5.4 编写调用后端接口的函数

代码如下所示:

// 根据ID获取详情信息
export const getDetApi = ({ params }: PropsData): any => {
  return fetch({url: `/galleryClassify/${params.id}`,method: 'get'})
}

4.5.5 在AdminController类中添加获取详情的方法

代码如下所示:

 /**
     * 获取详情信息
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public BaseResult detail(@PathVariable Long id){
        if(id == null){
            throw new BadRequestException("获取信息失败");
        }
        Admin dbAdmin = adminService.getById(id);
        return BaseResult.success(dbAdmin);
    }

4.5.6 在IAdminService接口下添加获取详情的方法

代码如下所示:

/**
     * 根据ID获取记录信息
     * @param id
     * @return
     */
    Admin getById(Long id);

4.5.7 在AdminServiceImpl接口实现类添加获取详情的方法

代码如下所示:

 /**
     * 根据ID获取详情信息
     * @param id
     * @return
     */
    @Override
    public Admin getById(Long id) {
        return adminRepository.findById(id).orElseGet(Admin::new);
    }

4.6 更新功能实现

4.6.1 在InfoWrite.vue文件下修改setListData函数

代码如下所示:

  // 提交表单的函数
    function setListData() {
      const formRefWrap = unref(formRef as any)
      try {
        subLoading.value = true
        formRefWrap.validate(async(valid:boolean) => {
          if (valid) {
            const formData = unref(form)
            if (form.id) { // 更新
              const res = await updateApi({
                data: formData
              })
              Message.success('更新成功')
              emit('success', 'edit')
            } else { // 新增
              const res = await addApi({
                data: formData
              })
              Message.success('添加成功')
              emit('success', 'add')
            }
          } else {
            console.log('error submit!!')
            return false
          }
        })
      } catch (err) {
        console.log(err)
      } finally {
        subLoading.value = false
      }
    }

4.6.2 在api.ts文件下新增updateApi接口函数

代码如下所示:

// 更新提交表单接口函数
export const updateApi = ({ data }: PropsData): any => {
  return fetch({ url: 'member', method: 'put', data })
}

4.6.3 在AdminController类下添加一个更新方法

代码如下所示:

  /**
     * 更新信息
     * @param admin
     * @return
     */
    @PutMapping
    public BaseResult update(@RequestBody Admin admin){
        adminService.update(admin);
        return BaseResult.success("更新成功");
    }

4.6.4 在IAdminService接口下添加一个更新方法

代码如下所示:

/**
     * 更新信息
     * @param admin
     */
    void update(Admin admin);

4.6.5 在AdminServiceImpl接口实现类添加一个更新方法

代码如下所示:

 /**
     *更新信息
     * @param admin
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Admin admin) {
        Admin dbAdmin = adminRepository.findById(admin.getId()).orElseGet(Admin::new);
        BeanUtil.copyProperties(admin,dbAdmin, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        adminRepository.save(dbAdmin);
    }

4.7 删除功能实现

4.7.1 在table表格添加删除按钮

代码如下所示:

 <!--表格按钮-->
    <template #action="scope">
      <el-button type="primary" size="mini" @click="open(scope.row,'InfoWrite')">编辑</el-button>
      <el-button type="danger" size="mini" @click="dels(scope.row)">删除</el-button>
    </template>

4.7.2 编写一个删除函数

代码如下所示:

// 删除(一条或多条)
    function dels(item?: any) {
      delData(async() => {
        let ids: string[] = []
        if(item.id){
          ids.push(item.id)
        } else {
          ids = selectionData.value.map((v: any) => {
            return v.id
          })
        }
        const res = await delsApi({
          data: JSON.stringify(ids)
        })
        if(res){
          Message.success(res.message)
          await getList()
        }
      }, { hiddenVerify: item.id })
    }


4.7.3 编写一个调用后端接口的delsApi函数

代码如下所示:

// 删除记录
export const delsApi = ({ data }: PropsData): any => {
  return fetch({ url: 'member', method: 'delete', data })
}

4.7.4 在AdminController类新增一个删除方法

代码如下所示:

 /**
     * 删除记录
     * @param ids
     * @return
     */
    @DeleteMapping
    public BaseResult delete(@RequestBody Long[] ids){
        try {
            adminService.delete(ids);
        }catch (Throwable e){
            ThrowableUtil.throwForeignKeyException(e,"删除失败,请稍候再试");
        }
        return BaseResult.success("删除成功");
    }

4.7.5 在IAdminService接口下新增一个删除方法

代码如下所示:

 /**
     * 删除信息
     * @param ids
     */
    void delete(Long[] ids);

4.7.6 在AdminServiceImpl接口实现类下新增一个删除方法

代码如下所示:

 /**
     * 删除信息
     * @param ids
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long[] ids) {
        adminRepository.deleteAllById(Arrays.stream(ids).toList());
    }

4.7.7 批量删除功能实现

修改index.vue批量删除按钮,代码如下所示:

<el-button
        type="danger"
        icon="el-icon-delete"
        @click="dels"
      >批量删除</el-button>

4.7.8 修改useExample()函数

代码如下所示:

const { dialogVisible, comName, title, defalutParams, loading, tableData, total,sizeChange,
      handleSelectionChange,toggleVisible, currentChange,selectionData,delData } = useExample()

4.7.9 修改return返回对象

代码如下所示:

return {
      info,
      dialogVisible,
      comName,
      toggleVisible,
      title,
      success,
      open,
      columns,
      loading,
      tableData,
      total,
      defalutParams,
      handleSelectionChange,
      handleSizeChange,
      handleCurrentChange,
      searchData,
      searchSubmit,
      resetSubmit,
      dels
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨鱼老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值