Web 毕设篇-适合小白、初级入门练手的 Spring Boot Web 毕业设计项目:智驿AI系统(前后端源码 + 数据库 sql 脚本)

发布于:2025-06-12 ⋅ 阅读:(13) ⋅ 点赞:(0)

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

文章目录

        AI系统具有许多优势

        1.0 项目介绍

        1.1 项目功能

        1.2 用户端功能

        2.0 用户登录

        3.0 首页界面

        4.0 物件管理功能

        5.0 用户管理功能

        6.0 区域管理功能

        7.0 物件日志管理功能

        8.0 操作日志


        AI系统具有许多优势

        1)自动化:AI 系统能够自动化执行任务,减少人力和时间成本。它们可以自动处理大量数据并执行复杂的计算,从而提高效率。

        2)智能决策:AI 系统可以通过学习和分析数据来做出智能决策。它们能够根据过去的经验和数据来预测未来的趋势,并提供有价值的见解。

        3)高精度和一致性:AI 系统在执行任务时通常能达到高精度和一致性。它们不受情绪或疲劳的影响,可以持续长时间地保持高质量的表现。

        4)大规模处理:AI 系统可以处理大规模的数据,并能够在短时间内快速地进行分析和处理。这使得它们特别适合处理需要大量数据处理的任务。

        5)个性化服务:AI 系统能够根据每个用户的需求和偏好提供个性化的服务。通过分析用户的数据和行为,AI 系统可以定制和优化用户体验。

        6)持续学习:AI 系统具有持续学习的能力,可以根据不断积累的数据和经验不断改进自身性能。这使得它们能够不断适应变化的环境和需求。

        总的来说,AI 系统的优势在于其自动化、智能化、高效率和灵活性,使其在各种领域都能发挥重要作用。

        1.0 项目介绍

        开发工具:IDEA、VScode

        服务器:Tomcat, JDK 17

        项目构建:maven

        数据库:mysql 8.0

系统用户前台和管理后台两部分,项目采用前后端分离

        前端技术:vue3 + elementUI

        服务端技术:springboot + mybatis + redis + mysql

        简单介绍一下,智驿AI系统主要分为两个端,系统管理端、用户端:

        1)系统管理端:

        2)用户端:

        1.1 项目功能

后台功能:

        1)登录、退出系统、首页

        2)物件管理

                (1) 物件管理:添加、修改、删除、查询等功能。

        3)用户管理

                (1) 用户管理:添加、修改、删除、查询等功能。

        4)区域管理

                (1) 区域管理:添加、修改、删除、查询等功能。

        5)物件日志管理

                (1) 物件日志管理:添加、修改、删除、查询等功能。

        6)用户反馈信息

                (1) 用户反馈信息:添加、修改、删除、查询等功能。

        7)操作日志

                (1) 操作日志:添加、修改、删除、查询等功能。

        8)物件入库

                (1)物件入库功能。

        9)系统管理

                用户信息管理

                        (1)用户信息管理:添加、修改、删除、查询等功能。

                角色管理

                        (2)角色信息管理:添加、修改、删除、查询等功能。

                菜单管理

                        (3)菜单信息管理:添加、修改、删除、查询等功能。

                日志管理

                        (4)日志信息管理:添加、修改、删除、查询等功能。

        10)系统监控

                        查看在先用户、设置定时任务、数据监控、缓存监控、查看缓存列表等。

        11)权限管理

                (1) 角色信息管理:添加、修改、删除、分配权限等功能。

                (2) 资源信息管理:添加、修改、删除等功能。

注意:不一定非要完全符合开发环境,有稍微的差别也是可以开发的。

         若需要项目完整源码,可以在 CSDN 私信给我,我每天都有查看消息的,感谢大家支持,希

望可以帮助到大家!

        1.2 用户端功能

        用户通过访问智能客服来询问快递的具体位置功能、用户信息反馈功能、用户取件功能:

相关源码:

<template>
  <div class="home" :class="{ 'dark': isDark }">
    <div class="container">
      <h1 class="title">取件 AI 应用中心</h1>
      <div class="cards-grid">
        <router-link 
          v-for="app in aiApps" 
          :key="app.id"
          :to="app.route"
          class="card"
          :aria-label="app.title"
        >
          <div class="card-content">
            <component :is="app.icon" class="icon" />
            <h2>{{ app.title }}</h2>
            <p>{{ app.description }}</p>
          </div>
        </router-link>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useDark } from '@vueuse/core'
import { 
  ChatBubbleLeftRightIcon,
  HeartIcon,
  UserGroupIcon,
  DocumentTextIcon
} from '@heroicons/vue/24/outline'

const isDark = useDark()

const aiApps = ref([
  {
    id: 1,
    title: 'AI 聊天',
    description: '多模态对话机器人,支持图片、音频等',
    route: '/ai-chat',
    icon: ChatBubbleLeftRightIcon
  },
 
  {
    id: 3,
    title: '快递取件智能客服',
    description: '24小时在线的智能咨询',
    route: '/customer-service',
    icon: UserGroupIcon
  }
  
])
</script>

<style scoped lang="scss">

  .container {
    max-width: 1600px;
    margin: 0 auto;
    padding: 0 2rem;
  }

  .title {
    text-align: center;
    font-size: 2.5rem;
    margin-bottom: 3rem;
    background: linear-gradient(45deg, #007CF0, #00DFD8);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: fadeIn 1s ease-out;
  }

  .cards-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10rem;
    padding: 1rem;
  }

  .card {
    width: 100%;
    max-width: 320px;
    background: rgba(255, 255, 255, 0.8);
    backdrop-filter: blur(10px);
    border-radius: 120px;
    padding: 2rem;
    text-decoration: none;
    color: inherit;
    transition: all 0.3s ease;
    border: 1px solid rgba(255, 255, 255, 0.1);
    overflow: hidden;

    &:hover {
      transform: translateY(-5px);
      box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
    }

    .dark & {
      background: rgba(255, 255, 255, 0.05);
      border: 1px solid rgba(255, 255, 255, 0.05);
      box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
    }

    .card-content {
      display: flex;
      flex-direction: column;
      align-items: center;
      text-align: center;
    }

    .icon {
      width: 48px;
      height: 48px;
      margin-bottom: 1rem;
      color: #007CF0;
    }

    h2 {
      font-size: 1.5rem;
      margin-bottom: 0.5rem;
    }

    p {
      color: #666;
      font-size: 1rem;
      line-height: 1.6;
    }

    .dark & p {
      color: #999;
    }
  }
}

</style>

 

        2.0 用户登录

        用户根据正确的用户名、密码且通过正确的校验码进行登录。

        用到了 Spring Security 框架来实现登录、校验、验证等功能。 

相关的部分源码:

@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;
 
    @Autowired
    private ISysMenuService menuService;
 
    @Autowired
    private SysPermissionService permissionService;
 
    /**
     * 登录方法
     * 
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }
 
    /**
     * 获取用户信息
     * 
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }
 
    /**
     * 获取路由信息
     * 
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }
}

        3.0 首页界面

        使用了各种各样的统计图表来直观展示数据。

相关的前端源码:

<template>
  <div class="stats-container">
    <!-- 页面标题 -->
    <h2>快递数据统计</h2>

    <!-- 统计卡片区域 -->
    <el-row :gutter="20" class="mb-4">
      <el-col :span="12">
        <el-card class="stat-card" shadow="hover">
          <div class="card-content">
            <div class="icon"><i class="el-icon-box"></i></div>
            
            <div class="info">
              <p class="title">今日入库数量</p>
              <p class="value">{{ stats.inbound }}</p>
            </div>

            <div class="info">
              <p class="title">入库总数量</p>
              <p class="value">{{ stats.inboundCount }}</p>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card class="stat-card" shadow="hover">
          <div class="card-content">
            <div class="icon"><i class="el-icon-truck"></i></div>
            
            <div class="info">
              <p class="title">今日出库数量</p>
              <p class="value">{{ stats.outbound }}</p>
            </div>

            <div class="info">
              <p class="title">出库总数量</p>
              <p class="value">{{ stats.outboundCount }}</p>
            </div>
          </div>
        </el-card>
      </el-col>
    </el-row>

    <!-- 图表区域 -->
    <el-row :gutter="20">
      <el-col :span="12">
        <el-card class="chart-card" shadow="never">
          <template #header>
            <div class="chart-header">快递入库统计</div>
          </template>
          <div ref="barChart" class="chart-container"></div>
        </el-card>
      </el-col>
      <el-col :span="12">
        <el-card class="chart-card" shadow="never">
          <template #header>
            <div class="chart-header">快递出库比例</div>
          </template>
          <div ref="pieChart" class="chart-container"></div>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import * as echarts from 'echarts'
import {getGoodsTodayCount} from '@/api/goods/goods'

// 模拟统计数据
const stats = ref({
  inbound: 0,
  outbound: 0,
  inboundCount:0,
  outboundCount:0
})

// 图表容器引用
const barChart = ref(null)
const pieChart = ref(null)

let barInstance = null
let pieInstance = null

// 初始化图表
function initCharts() {
  if (!barChart.value || !pieChart.value) return

  // 条形图配置(模拟数据)
  barInstance = echarts.init(barChart.value)
  barInstance.setOption({
    tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
    grid: { left: '5%', right: '5%', bottom: '10%' },
    xAxis: { type: 'category', data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'] },
    yAxis: {},
    series: [{ name: '入库数量', type: 'bar', data: [120, 200, 150, 80, 70, 110, 130], itemStyle: { color: '#409EFF' } }]
  })

  // 饼图配置(模拟数据)
  pieInstance = echarts.init(pieChart.value)
  pieInstance.setOption({
    tooltip: { trigger: 'item' },
    legend: { top: '5%', left: 'center' },
    series: [{
      name: '出库比例',
      type: 'pie',
      radius: '60%',
      data: [
        { value: 335, name: '华东' },
        { value: 310, name: '华北' },
        { value: 274, name: '华南' },
        { value: 235, name: '华中' }
      ],
      emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0, 0, 0, 0.5)' } },
      itemStyle: { borderRadius: 5, borderColor: '#fff', borderWidth: 2 }
    }]
  })
}

// 获取数据的方法(可替换为真实接口)
function fetchData() {
  
  
    // 异步请求
  getGoodsTodayCount().then((result) => {
    stats.value = result.data;
    stats.value = {
      inbound: result.data.todayInboundCount,
      outbound: result.data.todayOutboundCount,
      inboundCount:result.data.inboundCount,
      outboundCount:result.data.outboundCount
    }
    console.log(result.data);
  })

    // 更新图表数据(示例)
  updateChartData()
  
}

// 更新图表数据(预留方法用于接口回调后更新)
function updateChartData() {
  if (barInstance) {
    barInstance.setOption({
      series: [{ data: [100, 180, 140, 90, 80, 120, 110] }]
    })
  }

  if (pieInstance) {
    pieInstance.setOption({
      series: [{
        data: [
          { value: 280, name: '华东' },
          { value: 250, name: '华北' },
          { value: 200, name: '华南' },
          { value: 180, name: '华中' }
        ]
      }]
    })
  }
}

onMounted(() => {
  initCharts()
  fetchData()
})


</script>

<style scoped>
.stats-container {
  background-color: #ffffff;
  padding: 20px;
  min-height: 100vh;
  font-family: "Helvetica Neue", Arial, sans-serif;
}

.stat-card {
  background-color: #f5f7fa;
  border-radius: 12px;
  height: 120px;
}

.card-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 15px;
}

.icon {
  font-size: 40px;
  color: #409EFF;
}

.info .title {
  font-size: 16px;
  color: #666;
  margin-bottom: 5px;
}

.info .value {
  font-size: 24px;
  font-weight: bold;
  color: #333;
}

.chart-card {
  background-color: #f9fafb;
  border-radius: 12px;
}

.chart-header {
  font-size: 16px;
  font-weight: bold;
  text-align: center;
  color: #333;
}

.chart-container {
  width: 100%;
  height: 350px;
}
</style>

        4.0 物件管理功能

相关源码:

<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="手机号" prop="phoneNumber">
        <el-input
          v-model="queryParams.phoneNumber"
          placeholder="请输入手机号码"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
    
      <el-form-item label="状态" prop="state">
        <el-select v-model="queryParams.state" placeholder="请选择入库或者代表出库" clearable>
          <el-option
            v-for="dict in state"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="入库时间" prop="inboundTime">
        <el-date-picker clearable
          v-model="queryParams.inboundTime"
          type="date"
          value-format="YYYY-MM-DD"
          placeholder="请选择入库时间">
        </el-date-picker>
      </el-form-item>
      <el-form-item label="出库时间" prop="outboundTime">
        <el-date-picker clearable
          v-model="queryParams.outboundTime"
          type="date"
          value-format="YYYY-MM-DD"
          placeholder="请选择出库时间">
        </el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <!-- <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="Plus"
          @click="handleAdd"
          v-hasPermi="['goods:goods:add']"
        >新增</el-button>
      </el-col> -->
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="Edit"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['goods:goods:edit']"
        >修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="Delete"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['goods:goods:remove']"
        >删除</el-button>
      </el-col>
    
      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="goodsList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="物品序号"  width="80" align="center" prop="id" />
      <el-table-column label="手机号码" align="center" prop="phoneNumber" />
      <el-table-column label="物品入库位置" align="center" prop="regionId" >
        <template #default="scope">
          <!-- 遍历区域列表信息 -->
          <div v-for="region in regionOptions" :key="region.id">
            <span v-if="region.id === scope.row.regionId">{{ region.regionName + "-" + region.layer}}</span>
          </div>
        </template>
      </el-table-column>
      <el-table-column label="物品状态" align="center" prop="state">
        <template #default="scope">
          <dict-tag :options="state" :value="scope.row.state"/>
        </template>
      </el-table-column>
      <el-table-column label="入库时间" align="center" prop="inboundTime" width="180">
        <template #default="scope">
          <span>{{ parseTime(scope.row.inboundTime, '{y}-{m}-{d}') }}</span>
        </template>
      </el-table-column>
      <el-table-column label="出库时间" align="center" prop="outboundTime" width="180">
        <template #default="scope">
          <span v-if="scope.row.outboundTime != null && scope.row.outboundTime != ''">{{ parseTime(scope.row.outboundTime, '{y}-{m}-{d}') }}</span>
          <span v-else>待领取</span>
        </template>
      </el-table-column>
      <el-table-column label="存放时间" align="center" prop="storageTime" width="180">
        
        <template #default="scope">
          <span v-if="scope.row.outboundTime != null && scope.row.outboundTime != ''">
            {{
              scope.row.outboundTime === scope.row.inboundTime
                ? '当天入库'
                : Math.floor((new Date(scope.row.outboundTime) - new Date(scope.row.inboundTime)) / (1000 * 60 * 60 * 24)) + '天'
            }}
          </span>
          <span v-if="scope.row.outboundTime == null || scope.row.outboundTime == ''">
            {{
              Math.floor((new Date() - new Date(scope.row.inboundTime)) / (1000 * 60 * 60 * 24)) == '0'
                ? '当天入库'
                : Math.floor((new Date() - new Date(scope.row.inboundTime)) / (1000 * 60 * 60 * 24)) + '天'
            }}
          </span>
        </template>
        
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['goods:goods:edit']">修改</el-button>
          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['goods:goods:remove']">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <pagination
      v-show="total>0"
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改物件管理对话框 -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
      <el-form ref="goodsRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="手机号码" prop="phoneNumber">
          <el-input v-model="form.phoneNumber" placeholder="请输入用户手机号码" />
        </el-form-item>
        <el-form-item label="物件状态" prop="state">
          <el-select v-model="form.state" placeholder="请选择1代表入库;2代表出库">
            <el-option
              v-for="dict in state"
              :key="dict.value"
              :label="dict.label"
              :value="parseInt(dict.value)"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="入库时间" prop="inboundTime">
          <el-date-picker clearable
            v-model="form.inboundTime"
            type="date"
            value-format="YYYY-MM-DD"
            placeholder="请选择入库时间">
          </el-date-picker>
        </el-form-item>
        <el-form-item label="出库时间" prop="outboundTime">
          <el-date-picker clearable
            v-model="form.outboundTime"
            type="date"
            value-format="YYYY-MM-DD"
            placeholder="请选择出库时间">
          </el-date-picker>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="Goods">
import { listGoods, getGoods, delGoods, addGoods, updateGoods } from "@/api/goods/goods";
import {listRegion} from "@/api/region/region";
import { get } from "@vueuse/core";

const { proxy } = getCurrentInstance();
const { state } = proxy.useDict('state');

const goodsList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    phoneNumber: null,
    regionId: null,
    state: null,
    inboundTime: null,
    outboundTime: null,
    storageTime: null
  },
  rules: {
    phoneNumber: [
      { required: true, message: "用户手机号码不能为空", trigger: "blur" }
    ]/* ,
    regionId: [
      { required: true, message: "当前物品入库位置不能为空", trigger: "blur" }
    ], */
  }
});

const { queryParams, form, rules } = toRefs(data);

/** 查询物件管理列表 */
function getList() {
  loading.value = true;
  listGoods(queryParams.value).then(response => {
    goodsList.value = response.rows;
    total.value = response.total;
    loading.value = false;
  });
}

// 取消按钮
function cancel() {
  open.value = false;
  reset();
}

// 表单重置
function reset() {
  form.value = {
    id: null,
    phoneNumber: null,
    regionId: null,
    state: null,
    inboundTime: null,
    outboundTime: null,
    storageTime: null
  };
  proxy.resetForm("goodsRef");
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef");
  handleQuery();
}

// 多选框选中数据
function handleSelectionChange(selection) {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}

/** 新增按钮操作 */
function handleAdd() {
  reset();
  open.value = true;
  title.value = "添加物件管理";
}

/** 修改按钮操作 */
function handleUpdate(row) {
  reset();
  const _id = row.id || ids.value
  getGoods(_id).then(response => {
    form.value = response.data;
    open.value = true;
    title.value = "修改物件管理";
  });
}

/** 提交按钮 */
function submitForm() {
  proxy.$refs["goodsRef"].validate(valid => {
    if (valid) {
      if (form.value.id != null) {
        updateGoods(form.value).then(response => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        });
      } else {
        addGoods(form.value).then(response => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        });
      }
    }
  });
}

/** 删除按钮操作 */
function handleDelete(row) {
  const _ids = row.id || ids.value;
  proxy.$modal.confirm('是否确认删除物件管理编号为"' + _ids + '"的数据项?').then(function() {
    return delGoods(_ids);
  }).then(() => {
    getList();
    proxy.$modal.msgSuccess("删除成功");
  }).catch(() => {});
}

/** 导出按钮操作 */
function handleExport() {
  proxy.download('goods/goods/export', {
    ...queryParams.value
  }, `goods_${new Date().getTime()}.xlsx`)
}

getList();

const regionOptions = ref([]);
//查询区域列表
function getRegionList() {
  listRegion().then(response => {
    regionOptions.value = response.rows;
  });
}

getRegionList();



</script>

        5.0 用户管理功能

相关源码:

<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="用户名字" prop="userName">
        <el-input
          v-model="queryParams.userName"
          placeholder="请输入用户名字"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="电话号码" prop="phoneNumber">
        <el-input
          v-model="queryParams.phoneNumber"
          placeholder="请输入电话号码"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="Plus"
          @click="handleAdd"
          v-hasPermi="['tbUser:tbuser:add']"
        >新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="Edit"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['tbUser:tbuser:edit']"
        >修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="Delete"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['tbUser:tbuser:remove']"
        >删除</el-button>
      </el-col>
      
      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="tbuserList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="用户序号" type="index" width="130" align="center" prop="id" />
      <el-table-column label="用户名字" align="center" prop="userName" width="180"/>
      <el-table-column label="用户号码" align="center" prop="phoneNumber" width="280" />
      <el-table-column label="用户图片" align="center" prop="img" width="200">
        <template #default="scope">
          <image-preview :src="scope.row.img" :width="80" :height="60"/>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['tbUser:tbuser:edit']">修改</el-button>
          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['tbUser:tbuser:remove']">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <pagination
      v-show="total>0"
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改用户管理对话框 -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
      <el-form ref="tbuserRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="用户名字" prop="userName">
          <el-input v-model="form.userName" placeholder="请输入用户名字" />
        </el-form-item>
        <el-form-item label="用户号码" prop="phoneNumber">
          <el-input v-model="form.phoneNumber" placeholder="请输入用户号码" />
        </el-form-item>
        <el-form-item label="用户图片" prop="img">
          <image-upload v-model="form.img"/>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="Tbuser">
import { listTbuser, getTbuser, delTbuser, addTbuser, updateTbuser } from "@/api/tbUser/tbuser";

const { proxy } = getCurrentInstance();

const tbuserList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    userName: null,
    phoneNumber: null,
    img: null
  },
  rules: {
    userName: [
      { required: true, message: "用户名字不能为空", trigger: "blur" }
    ],
    phoneNumber: [
      { required: true, message: "用户号码不能为空", trigger: "blur" }
    ]
  }
});

const { queryParams, form, rules } = toRefs(data);

/** 查询用户管理列表 */
function getList() {
  loading.value = true;
  listTbuser(queryParams.value).then(response => {
    tbuserList.value = response.rows;
    total.value = response.total;
    loading.value = false;
  });
}

// 取消按钮
function cancel() {
  open.value = false;
  reset();
}

// 表单重置
function reset() {
  form.value = {
    id: null,
    userName: null,
    phoneNumber: null,
    img: null
  };
  proxy.resetForm("tbuserRef");
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef");
  handleQuery();
}

// 多选框选中数据
function handleSelectionChange(selection) {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}

/** 新增按钮操作 */
function handleAdd() {
  reset();
  open.value = true;
  title.value = "添加用户管理";
}

/** 修改按钮操作 */
function handleUpdate(row) {
  reset();
  const _id = row.id || ids.value
  getTbuser(_id).then(response => {
    form.value = response.data;
    open.value = true;
    title.value = "修改用户管理";
  });
}

/** 提交按钮 */
function submitForm() {
  proxy.$refs["tbuserRef"].validate(valid => {
    if (valid) {
      if (form.value.id != null) {
        updateTbuser(form.value).then(response => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        });
      } else {
        addTbuser(form.value).then(response => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        });
      }
    }
  });
}

/** 删除按钮操作 */
function handleDelete(row) {
  const _ids = row.id || ids.value;
  proxy.$modal.confirm('是否确认删除用户的数据项?').then(function() {
    return delTbuser(_ids);
  }).then(() => {
    getList();
    proxy.$modal.msgSuccess("删除成功");
  }).catch(() => {});
}

/** 导出按钮操作 */
function handleExport() {
  proxy.download('tbUser/tbuser/export', {
    ...queryParams.value
  }, `tbuser_${new Date().getTime()}.xlsx`)
}

getList();
</script>

        6.0 区域管理功能

相关源码:

<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="区域名" prop="regionName">
        <el-input
          v-model="queryParams.regionName"
          placeholder="请输入区域名"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="容量" prop="capacity">
        <el-input
          v-model="queryParams.capacity"
          placeholder="请输入容量"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item label="当前容量" prop="currentQuantity">
        <el-input
          v-model="queryParams.currentQuantity"
          placeholder="请输入当前容量"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="Plus"
          @click="handleAdd"
          v-hasPermi="['region:region:add']"
        >新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="Edit"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['region:region:edit']"
        >修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="Delete"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['region:region:remove']"
        >删除</el-button>
      </el-col>
      
      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="regionList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="区域序号" type="index" align="center" prop="id" width="80" />
      <el-table-column label="区域名" align="center" prop="regionName" />
      <el-table-column label="货架层级" align="center" prop="layer" width="110"/>
      <el-table-column label="区域图片" align="center" prop="img" width="180">
        <template #default="scope">
          <image-preview :src="scope.row.img" :width="80" :height="60"/>
        </template>
      </el-table-column>
      
      <el-table-column label="容量" align="center" prop="capacity" />
      <el-table-column label="当前件数" align="center" prop="currentQuantity" />
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['region:region:edit']">修改</el-button>
          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['region:region:remove']">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <pagination
      v-show="total>0"
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改区域对话框 -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
      <el-form ref="regionRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="区域名" prop="regionName">
          <el-input v-model="form.regionName" placeholder="请输入区域名" />
        </el-form-item>
        <el-form-item label="区域图片" prop="img">
          <image-upload v-model="form.img"/>
        </el-form-item>
        <el-form-item label="层数" prop="layer">
          <el-input v-model="form.layer" placeholder="请输入层数" />
        </el-form-item>
        <el-form-item label="容量" prop="capacity">
          <el-input v-model="form.capacity" placeholder="请输入容量" />
        </el-form-item>
        <!-- <el-form-item label="当前容量" prop="currentQuantity">
          <el-input v-model="form.currentQuantity" placeholder="请输入当前容量" />
        </el-form-item> -->
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="Region">
import { listRegion, getRegion, delRegion, addRegion, updateRegion } from "@/api/region/region";

const { proxy } = getCurrentInstance();

const regionList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    regionName: null,
    img: null,
    layer: null,
    capacity: null,
    currentQuantity: null
  },
  rules: {
    regionName: [
      { required: true, message: "区域名不能为空", trigger: "blur" }
    ],
    layer: [
      { required: true, message: "层数不能为空", trigger: "blur" }
    ],
    capacity: [
      { required: true, message: "容量不能为空", trigger: "blur" }
    ]
  }
});

const { queryParams, form, rules } = toRefs(data);

/** 查询区域列表 */
function getList() {
  loading.value = true;
  listRegion(queryParams.value).then(response => {
    regionList.value = response.rows;
    total.value = response.total;
    loading.value = false;
  });
}

// 取消按钮
function cancel() {
  open.value = false;
  reset();
}

// 表单重置
function reset() {
  form.value = {
    id: null,
    regionName: null,
    img: null,
    layer: null,
    capacity: null,
    currentQuantity: null
  };
  proxy.resetForm("regionRef");
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef");
  handleQuery();
}

// 多选框选中数据
function handleSelectionChange(selection) {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}

/** 新增按钮操作 */
function handleAdd() {
  reset();
  open.value = true;
  title.value = "添加区域";
}

/** 修改按钮操作 */
function handleUpdate(row) {
  reset();
  const _id = row.id || ids.value
  getRegion(_id).then(response => {
    form.value = response.data;
    open.value = true;
    title.value = "修改区域";
  });
}

/** 提交按钮 */
function submitForm() {
  proxy.$refs["regionRef"].validate(valid => {
    if (valid) {
      if (form.value.id != null) {
        updateRegion(form.value).then(response => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        });
      } else {
        addRegion(form.value).then(response => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        });
      }
    }
  });
}

/** 删除按钮操作 */
function handleDelete(row) {
  const _ids = row.id || ids.value;
  proxy.$modal.confirm('是否确认删除区域的数据项?').then(function() {
    return delRegion(_ids);
  }).then(() => {
    getList();
    proxy.$modal.msgSuccess("删除成功");
  }).catch(() => {});
}

/** 导出按钮操作 */
function handleExport() {
  proxy.download('region/region/export', {
    ...queryParams.value
  }, `region_${new Date().getTime()}.xlsx`)
}

getList();
</script>

        7.0 物件日志管理功能

相关源码:

<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="用户号码" prop="number">
        <el-input
          v-model="queryParams.number"
          placeholder="请输入用户号码"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <!-- <el-form-item label="物品id" prop="goodsId">
        <el-input
          v-model="queryParams.goodsId"
          placeholder="请输入物品id"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item> -->
      <el-form-item label="入库时间" prop="inboundTime">
        <el-date-picker clearable
          v-model="queryParams.inboundTime"
          type="date"
          value-format="YYYY-MM-DD"
          placeholder="请选择入库时间">
        </el-date-picker>
      </el-form-item>
      <el-form-item label="出库时间" prop="outboundTime">
        <el-date-picker clearable
          v-model="queryParams.outboundTime"
          type="date"
          value-format="YYYY-MM-DD"
          placeholder="请选择出库时间">
        </el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="Plus"
          @click="handleAdd"
          v-hasPermi="['ItemLog:Itemlog:add']"
        >新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="Edit"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['ItemLog:Itemlog:edit']"
        >修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="Delete"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['ItemLog:Itemlog:remove']"
        >删除</el-button>
      </el-col>
    
      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="ItemlogList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="物品日志序号" type="index" width="130" align="center" prop="id" />
      <el-table-column label="手机号码" align="center" prop="number" />
      <el-table-column label="物品唯一标识" align="center" prop="goodsId" />
      <el-table-column label="入库时间" align="center" prop="inboundTime" width="180">
        <template #default="scope">
          <span>{{ parseTime(scope.row.inboundTime, '{y}-{m}-{d}') }}</span>
        </template>
      </el-table-column>
      <el-table-column label="出库时间" align="center" prop="outboundTime" width="180">
        <template #default="scope">
          <span>{{ parseTime(scope.row.outboundTime, '{y}-{m}-{d}') }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['ItemLog:Itemlog:edit']">修改</el-button>
          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['ItemLog:Itemlog:remove']">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <pagination
      v-show="total>0"
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改物件日志管理对话框 -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
      <el-form ref="ItemlogRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="手机号码" prop="number">
          <el-input v-model="form.number" placeholder="请输入用户手机号码" />
        </el-form-item>
        <el-form-item label="物品标识" prop="goodsId">
          <el-input v-model="form.goodsId" placeholder="请输入物品id" />
        </el-form-item>
        <el-form-item label="入库时间" prop="inboundTime">
          <el-date-picker clearable
            v-model="form.inboundTime"
            type="date"
            value-format="YYYY-MM-DD"
            placeholder="请选择入库时间">
          </el-date-picker>
        </el-form-item>
        <el-form-item label="出库时间" prop="outboundTime">
          <el-date-picker clearable
            v-model="form.outboundTime"
            type="date"
            value-format="YYYY-MM-DD"
            placeholder="请选择出库时间">
          </el-date-picker>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="Itemlog">
import { listItemlog, getItemlog, delItemlog, addItemlog, updateItemlog } from "@/api/ItemLog/Itemlog";

const { proxy } = getCurrentInstance();

const ItemlogList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    number: null,
    goodsId: null,
    inboundTime: null,
    outboundTime: null
  },
  rules: {
    number: [
      { required: true, message: "管理id/用户号码不能为空", trigger: "blur" }
    ],
    goodsId: [
      { required: true, message: "物品id不能为空", trigger: "blur" }
    ],
    inboundTime: [
      { required: true, message: "入库时间不能为空", trigger: "blur" }
    ],
    outboundTime: [
      { required: true, message: "出库时间不能为空", trigger: "blur" }
    ]
  }
});

const { queryParams, form, rules } = toRefs(data);

/** 查询物件日志管理列表 */
function getList() {
  loading.value = true;
  listItemlog(queryParams.value).then(response => {
    ItemlogList.value = response.rows;
    total.value = response.total;
    loading.value = false;
  });
}

// 取消按钮
function cancel() {
  open.value = false;
  reset();
}

// 表单重置
function reset() {
  form.value = {
    id: null,
    number: null,
    goodsId: null,
    inboundTime: null,
    outboundTime: null
  };
  proxy.resetForm("ItemlogRef");
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef");
  handleQuery();
}

// 多选框选中数据
function handleSelectionChange(selection) {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}

/** 新增按钮操作 */
function handleAdd() {
  reset();
  open.value = true;
  title.value = "添加物件日志管理";
}

/** 修改按钮操作 */
function handleUpdate(row) {
  reset();
  const _id = row.id || ids.value
  getItemlog(_id).then(response => {
    form.value = response.data;
    open.value = true;
    title.value = "修改物件日志管理";
  });
}

/** 提交按钮 */
function submitForm() {
  proxy.$refs["ItemlogRef"].validate(valid => {
    if (valid) {
      if (form.value.id != null) {
        updateItemlog(form.value).then(response => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        });
      } else {
        addItemlog(form.value).then(response => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        });
      }
    }
  });
}

/** 删除按钮操作 */
function handleDelete(row) {
  const _ids = row.id || ids.value;
  proxy.$modal.confirm('是否确认删除物件日志管理编号为"' + _ids + '"的数据项?').then(function() {
    return delItemlog(_ids);
  }).then(() => {
    getList();
    proxy.$modal.msgSuccess("删除成功");
  }).catch(() => {});
}

/** 导出按钮操作 */
function handleExport() {
  proxy.download('ItemLog/Itemlog/export', {
    ...queryParams.value
  }, `Itemlog_${new Date().getTime()}.xlsx`)
}

getList();
</script>

        8.0 操作日志

相关源码:

<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="100px">
      <el-form-item label="操作人员" prop="adminId">
        <el-input
          v-model="queryParams.adminId"
          placeholder="请输入操作人员唯一标识"
          clearable
          @keyup.enter="handleQuery"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          plain
          icon="Plus"
          @click="handleAdd"
          v-hasPermi="['optionLog:log:add']"
        >新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          plain
          icon="Edit"
          :disabled="single"
          @click="handleUpdate"
          v-hasPermi="['optionLog:log:edit']"
        >修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          plain
          icon="Delete"
          :disabled="multiple"
          @click="handleDelete"
          v-hasPermi="['optionLog:log:remove']"
        >删除</el-button>
      </el-col>
      
      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="logList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="操作日志序号" type="index" width="130" align="center" prop="id" />
      <!-- <el-table-column label="操作信息" align="center" prop="msg" width="100" /> -->
      <el-table-column label="操作信息" align="center" prop="msg" width="400">
        <template #default="scope">
          <el-tooltip :content="scope.row.msg" placement="top" :disabled="!scope.row.msg || scope.row.msg.length <= 10">
            <span>{{ scope.row.msg }}</span>
          </el-tooltip>
        </template>
      </el-table-column>
      <el-table-column label="操作人员唯一标识" align="center" prop="adminId" />
      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
        <template #default="scope">
          <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template #default="scope">
          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['optionLog:log:edit']">修改</el-button>
          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['optionLog:log:remove']">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <pagination
      v-show="total>0"
      :total="total"
      v-model:page="queryParams.pageNum"
      v-model:limit="queryParams.pageSize"
      @pagination="getList"
    />

    <!-- 添加或修改操作日志对话框 -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
      <el-form ref="logRef" :model="form" :rules="rules" label-width="80px">
        
        <el-form-item label="操作人员" prop="adminId">
          <el-input v-model="form.adminId" placeholder="请输入操作人员唯一标识" />
        </el-form-item>

        <el-form-item label="操作信息" prop="msg">
          <el-input v-model="form.msg" placeholder="请输入操作信息" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">确 定</el-button>
          <el-button @click="cancel">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="Log">
import { listLog, getLog, delLog, addLog, updateLog } from "@/api/optionLog/log";

const { proxy } = getCurrentInstance();

const logList = ref([]);
const open = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const title = ref("");

const data = reactive({
  form: {},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    adminId: null,
  },
  rules: {
    msg: [
      { required: true, message: "操作信息不能为空", trigger: "blur" }
    ],
    adminId: [
      { required: true, message: "操作人员id不能为空", trigger: "blur" }
    ],
  }
});

const { queryParams, form, rules } = toRefs(data);

/** 查询操作日志列表 */
function getList() {
  loading.value = true;
  listLog(queryParams.value).then(response => {
    logList.value = response.rows;
    total.value = response.total;
    loading.value = false;
  });
}

// 取消按钮
function cancel() {
  open.value = false;
  reset();
}

// 表单重置
function reset() {
  form.value = {
    id: null,
    msg: null,
    adminId: null,
    createTime: null
  };
  proxy.resetForm("logRef");
}

/** 搜索按钮操作 */
function handleQuery() {
  queryParams.value.pageNum = 1;
  getList();
}

/** 重置按钮操作 */
function resetQuery() {
  proxy.resetForm("queryRef");
  handleQuery();
}

// 多选框选中数据
function handleSelectionChange(selection) {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}

/** 新增按钮操作 */
function handleAdd() {
  reset();
  open.value = true;
  title.value = "添加操作日志";
}

/** 修改按钮操作 */
function handleUpdate(row) {
  reset();
  const _id = row.id || ids.value
  getLog(_id).then(response => {
    form.value = response.data;
    open.value = true;
    title.value = "修改操作日志";
  });
}

/** 提交按钮 */
function submitForm() {
  proxy.$refs["logRef"].validate(valid => {
    if (valid) {
      if (form.value.id != null) {
        updateLog(form.value).then(response => {
          proxy.$modal.msgSuccess("修改成功");
          open.value = false;
          getList();
        });
      } else {
        addLog(form.value).then(response => {
          proxy.$modal.msgSuccess("新增成功");
          open.value = false;
          getList();
        });
      }
    }
  });
}

/** 删除按钮操作 */
function handleDelete(row) {
  const _ids = row.id || ids.value;
  proxy.$modal.confirm('是否确认删除操作日志编号为"' + _ids + '"的数据项?').then(function() {
    return delLog(_ids);
  }).then(() => {
    getList();
    proxy.$modal.msgSuccess("删除成功");
  }).catch(() => {});
}

/** 导出按钮操作 */
function handleExport() {
  proxy.download('optionLog/log/export', {
    ...queryParams.value
  }, `log_${new Date().getTime()}.xlsx`)
}

getList();
</script>

        若需要项目完整源码,可以在 CSDN 私信给我或者直接+我名片,我每天都有查看消息的,感谢大家支持,希望可以帮助到大家!