Vue3 如何让代码变得清新优雅,代码洁癖患者进!(4)

发布时间 2023-06-05 10:54:34作者: kitty20180903suzhou

列表页面 来啦!
温馨提示:

在 列表页面中,使用 若依的分页组件: Pagination,图片预览组件:ImagePreview,标签组件 DictTag ,还有公共方法 parseTime 等等 对若依 respect !

搜索 或 翻页时 通过 router.push 跳转路由,使用 onBeforeRouteUpdate 监听路由变化,然后获取页面数据 getList

注意,搜索条件里没有 pageNum 和 pageSize,把她放在列表页面更好。

只是举个栗子,大家别当真 list.vue:

<template>
    <div class="app-container" v-hasPermi="actions['search'].permission">
        <!-- 需求管理 -->
        <!-- 搜索 -->
        <Search ref="searchRef" @search="search" :showSearch="showSearch" :dicts="dicts"/>
        <!-- 批量操作 -->
        <BatchOperation 
            :actions="actions" 
            @create="handleCreate"
            >
            <template #rightToolbar>
                <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
            </template>
        </BatchOperation>
        <el-table :data="list" row-key="demandId" @expand-change="expandChange" :expand-row-keys="expandRowKeys" scrollbar-always-on>
            <el-table-column type="expand" fixed="left">
                <template #default="{row}">
                    <el-descriptions class="margin-top" :column="2" border>
                        <el-descriptions-item label="封面图" :span="2" width="150px" label-align="right">
                          <ImagePreview :src="row.urlOss.map(z=>z.url).join(',')||defaultThumb" v-if="Array.isArray(row.urlOss)" height="100px"/>
                        </el-descriptions-item>
                        <el-descriptions-item label="需求说明" :span="2" width="150px" label-align="right">
                            <div v-html="row.content" class="ql-snow ql-editor"></div>
                        </el-descriptions-item>
                        <el-descriptions-item label="备注" :span="2" width="150px" label-align="right">
                            {{row.remark}}
                        </el-descriptions-item>
                    </el-descriptions>
                </template>
            </el-table-column>
            <el-table-column label="需求名称" header-align="center" prop="name" width="260" fixed="left" ></el-table-column>
            <el-table-column label="审核状态" prop="checkStatus" width="150" align="center">
                <template #default="{row}">
                    <div style="display:flex;justify-content: center;">
                        <dict-tag :options="dicts.sys_checkStatus" :value="row.checkStatus" />
                        <span v-if="row.checkStatus == 2">
                            <el-divider direction="vertical"></el-divider>
                            <el-popover
                                placement="top"
                                width="200"
                                trigger="hover"
                                :content="row.checkMessage">
                                <template #reference>
                                    <el-button link type="danger">原因</el-button>
                                </template>
                            </el-popover>
                        </span>
                    </div>
                </template>
            </el-table-column>
            <el-table-column label="是否上架" prop="status" width="150" align="center">
                <template #default="{row}">
                    <dict-tag :options="dicts.demand_status" :value="row.status" />
                </template>
            </el-table-column>
            <el-table-column label="需求预算" prop="budget" width="150" align="center" >
                <template #default="{row}">
                    <span>{{ moneyFormat(row.budget) }}</span>
                </template>
            </el-table-column>
            <el-table-column label="需求类型" prop="category" width="150" align="center">
                <template #default="{row}">
                    <dict-tag :options="dicts.demand_category" :value="row.status" />
                </template>
            </el-table-column>
            <el-table-column label="交易数量" width="150" align="center">
                <template #default="{row}">
                    <span>{{row.total || '--'}}</span>
                </template>
            </el-table-column>
            <el-table-column label="截止时间" header-align="center" prop="deadline" width="120" show-overflow-tooltip>
                 <template #default="{row}">
                    <span>{{ row.deadline ? parseTime(row.deadline,'{y}-{m}-{d}') : '长期有效' }}</span>
                </template>
            </el-table-column>
            <el-table-column label="联系人" header-align="center" prop="userName" width="180" show-overflow-tooltip>
                <template #default="{row}">
                    <span>{{ row.customerName}}</span>
                    <br/>
                    <span>{{row.userName }}</span>
                    <el-divider direction="vertical"></el-divider>
                    <span>{{row.tel}}</span>
                </template>
            </el-table-column>
            <el-table-column label="发布时间" align="center" prop="releaseTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
                <template #default="{row}">
                    <span>{{ parseTime(row.releaseTime,'{y}年{m}月{d}日')}} </span>
                </template>
            </el-table-column>
            <el-table-column label="创建时间" align="center" show-overflow-tooltip prop="createTime" width="180"></el-table-column>
            <el-table-column label="操作" fixed="right" header-align="center" width="150px">
              <template #default="{row}">
                <BatchOperation 
                  :inColumn="true"
                  :actions="initAction(false, false, row)"
                  @check="handleCheck(row)"
                  @edit="handleEdit(row)"
                  @delete="handleDelete(row.demandId)"
                  ></BatchOperation>
              </template>
            </el-table-column>
        </el-table>
        <!-- 分页 -->
        <Pagination :hidden="total<=pager.pageSize" :total="total" v-model:page="pager.pageNum" v-model:limit="pager.pageSize" @pagination="pagination"></Pagination>
        <!-- 审核 -->
        <div v-hasPermi="actions['check'].permission"><Check ref="checkRef" @refresh="getList" /></div>
    </div>
</template>

<script setup name="DemandIndex">
import { getPages, remove } from '@/api/demand'
import defaultThumb from '@/assets/images/diagrams/demand-default-thumb.jpg'
import Check from './components/check.vue'
import Search from './components/search.vue'
import initAction from './components/actions'
const { proxy } = getCurrentInstance()
// 字典
const dicts = ref({})
// 使用路由
const router = useRouter()
const route = useRoute()
// 列表相关
const list = ref([]) // 列表数据
const pager = ref({ // 列表数据页码
  pageNum: Number(route.query.pageNum) || 1,
  pageSize: Number(route.query.pageSize) || 20
})
const total = ref(0) // 列表总条数
// 默认展开行 keys
const expandRowKeys = ref([])
// 搜索相关 
const searchRef = ref(null) // ref
const showSearch = ref(true)// 是否显示搜索
// 勾选
const multipleSelection = ref([])
// 非单个禁用
const single = computed(() => multipleSelection.value.length != 1)
// 非多个禁用
const multiple = computed(() => !multipleSelection.value.length)
// 当前选中
const selectedRow = computed(()=>{
  if(multipleSelection.value.length == 1){
    return list.value.find(z => z.demandId == multipleSelection.value[0])
  }
  return null
})
// 批量操作按钮
const actions = computed(()=>initAction(single.value, multiple.value, selectedRow.value))
// 审核 ref
const checkRef = ref(null)
// 点击 发布需求
const handleCreate =()=>{
    router.push('/demand/create')
}
// 点击 审核
const handleCheck =(row)=>{
    const current = row || selectedRow.value
    checkRef.value.init(current)
}
// 点击 编辑
const handleEdit =(row)=>{
    const current = row || selectedRow.value
    router.push('/demand/edit/' + current.demandId)
}
// 展开详情
const expandChange = async (row,expandedRows)=>{
    const index = expandedRows.findIndex(z=>z.demandId== row.demandId)
    if(index == -1) return
    row.urlOss = await proxy.getFileList(row.urlOss)
    expandRowKeys.value = expandedRows.map(z=>z.demandId)
}
// 获取列表数据
const getList = () => {
  proxy.$modal.loading("加载中...")
  const { dateRange, ...search } = searchRef.value.form
  const query = { ...pager.value, ...search }
  const data = dateRange ? proxy.addDateRange(query, dateRange) : query
  getPages(data).then(response => {
    list.value = response.data.rows;
    total.value = parseInt(response.data.total);
    expandRowKeys.value = []
  }).finally(() => {
    proxy.$modal.closeLoading();
  });
}
// 搜索
const search = () => {
  pager.value.pageNum = 1
  pagination()
}
// 翻页页面
const pagination = () => {
  const { params, ...routeQuery } = searchRef.value.form
  router.push({
    path: route.path,
    query: {
      ...pager.value,
      ...routeQuery
    }
  }).then((res1)=>{
      // 路由及参数重复
      if(res1 && res1.to.fullPath === res1.from.fullPath){
          getList()
      }
  })
}
// 勾选
const handleSelectionChange = (val) => {
  multipleSelection.value = val.map(z => z.demandId)
}
// 批量删除
const handleDelete = (id) => {
  proxy.$modal.confirm('确定删除?')
    .then(() => {
      const ids = id || multipleSelection.value
      remove(ids).then(res => {
        if (res.code == 200) {
          proxy.$modal.msgSuccess("操作成功")
          getList()
        } else {
          proxy.$modal.msgError(res.msg || "请求发生错误,请稍后重试")
        }
      })
    })
    .catch(() => {
      proxy.$modal.msg("已取消")
    })
}
// 监听路由变化
onBeforeRouteUpdate((to, from, next) => {
    const newVal = to.query
    searchRef.value.setQueryData(newVal)
    pager.value.pageNum = Number(newVal.pageNum) || 1
    pager.value.pageSize = Number(newVal.pageSize) || 20
    // 获取列表
    getList()
    next()
})
onMounted(()=>{
    dicts.value = proxy.useDict('sys_checkStatus', 'demand_status','demand_category')
    getList()
})
</script>
<style scoped lang="scss">
.input-with-select{
  width: 480px;
  ::v-deep .el-select .el-input {
    width: 150px;
  }
}

</style>