feat: use project standard search bar pattern for asset pages, add title/phone/date filters

This commit is contained in:
2026-05-21 09:54:59 +08:00
parent a42fc6453a
commit 4c3becf33e
4 changed files with 131 additions and 40 deletions
+78 -34
View File
@@ -1,19 +1,39 @@
<template> <template>
<div class="asset-resource-container"> <div class="asset-resource-container">
<el-card shadow="never" class="!border-none"> <!-- 搜索区域 -->
<div class="mb-4 flex items-center gap-4 flex-wrap"> <el-card class="!border-none" shadow="never">
<el-button type="primary" @click="handleAdd">上传并分发资源</el-button> <el-form class="ls-form" :model="searchData" inline>
<el-date-picker <el-form-item class="w-[280px]" label="标题">
v-model="dateRange" <el-input
type="daterange" placeholder="请输入标题关键词"
range-separator="" v-model="searchData.title"
start-placeholder="开始日期" clearable
end-placeholder="结束日期" @keyup.enter="handleSearch"
value-format="YYYY-MM-DD" />
@change="handleDateChange" </el-form-item>
clearable <el-form-item label="上传时间">
style="width: 300px;" <el-date-picker
/> v-model="searchData.dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
clearable
style="width: 280px;"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 列表区域 -->
<el-card class="!border-none mt-4" shadow="never">
<div class="mb-4">
<el-button type="primary" @click="handleAdd">上传资源</el-button>
</div> </div>
<el-tabs v-model="queryParams.type" @tab-change="handleTabChange"> <el-tabs v-model="queryParams.type" @tab-change="handleTabChange">
@@ -24,14 +44,14 @@
<el-table :data="tableData" v-loading="loading"> <el-table :data="tableData" v-loading="loading">
<el-table-column prop="id" label="ID" width="80" /> <el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="title" label="标题" /> <el-table-column prop="title" label="标题" min-width="150" />
<el-table-column label="预览"> <el-table-column label="预览" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-image v-if="row.type == 1" :src="row.file_url" style="width: 50px; height: 50px;" :preview-src-list="[row.file_url]" preview-teleported /> <el-image v-if="row.type == 1" :src="row.file_url" style="width: 50px; height: 50px;" :preview-src-list="[row.file_url]" preview-teleported />
<el-link v-else :href="row.file_url" target="_blank" type="primary">点击预览</el-link> <el-link v-else :href="row.file_url" target="_blank" type="primary">点击预览</el-link>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="关联账号" show-overflow-tooltip> <el-table-column label="关联账号" min-width="150" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<el-tag v-if="!row.users?.length" type="info" size="small">公开资源</el-tag> <el-tag v-if="!row.users?.length" type="info" size="small">公开资源</el-tag>
<span v-else>{{ row.users?.map((u: any) => u.phone).join(', ') }}</span> <span v-else>{{ row.users?.map((u: any) => u.phone).join(', ') }}</span>
@@ -58,9 +78,9 @@
</div> </div>
</el-card> </el-card>
<!-- 新增资源弹窗 --> <!-- 新增/编辑资源弹窗 -->
<el-dialog v-model="dialogVisible" :title="isEdit ? '编辑资源' : '新增分发资源'" width="600px" destroy-on-close> <el-dialog v-model="dialogVisible" :title="isEdit ? '编辑资源' : '新增分发资源'" width="600px" destroy-on-close>
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px"> <el-form ref="formRef" :model="formData" :rules="computedRules" label-width="100px">
<el-form-item label="资源类型" prop="type" v-if="!isEdit"> <el-form-item label="资源类型" prop="type" v-if="!isEdit">
<el-radio-group v-model="formData.type"> <el-radio-group v-model="formData.type">
<el-radio :label="1">图片</el-radio> <el-radio :label="1">图片</el-radio>
@@ -99,7 +119,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, onMounted } from 'vue' import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
import { apiAssetResourceList, apiAssetResourceAdd, apiAssetResourceEdit, apiAssetResourceDelete, apiAssetUserList } from '@/api/asset' import { apiAssetResourceList, apiAssetResourceAdd, apiAssetResourceEdit, apiAssetResourceDelete, apiAssetUserList } from '@/api/asset'
import MaterialPicker from '@/components/material/picker.vue' import MaterialPicker from '@/components/material/picker.vue'
@@ -108,7 +128,12 @@ import Upload from '@/components/upload/index.vue'
const loading = ref(false) const loading = ref(false)
const tableData = ref([]) const tableData = ref([])
const total = ref(0) const total = ref(0)
const dateRange = ref<string[]>([])
const searchData = reactive<any>({
title: '',
dateRange: []
})
const queryParams = reactive<any>({ const queryParams = reactive<any>({
type: '1', type: '1',
page_no: 1, page_no: 1,
@@ -131,15 +156,34 @@ const formData = reactive<any>({
user_ids: [] user_ids: []
}) })
const rules = { const computedRules = computed(() => {
title: [{ required: true, message: '请输入标题', trigger: 'blur' }], if (isEdit.value) {
file_url: [{ required: true, message: '请输入或上传文件获取链接', trigger: 'blur' }] return {
title: [{ required: true, message: '请输入标题', trigger: 'blur' }]
}
}
return {
title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
file_url: [{ required: true, message: '请输入或上传文件获取链接', trigger: 'blur' }]
}
})
const buildQueryParams = () => {
const params: any = { ...queryParams }
if (searchData.title) {
params.title = searchData.title
}
if (searchData.dateRange && searchData.dateRange.length === 2) {
params.start_time = searchData.dateRange[0]
params.end_time = searchData.dateRange[1]
}
return params
} }
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true
try { try {
const res = await apiAssetResourceList(queryParams) const res = await apiAssetResourceList(buildQueryParams())
tableData.value = res.lists tableData.value = res.lists
total.value = res.count total.value = res.count
} catch (e) { } catch (e) {
@@ -158,19 +202,19 @@ const fetchUserOptions = async () => {
} }
} }
const handleTabChange = () => { const handleSearch = () => {
queryParams.page_no = 1 queryParams.page_no = 1
getList() getList()
} }
const handleDateChange = (val: string[] | null) => { const handleReset = () => {
if (val && val.length === 2) { searchData.title = ''
queryParams.start_time = val[0] searchData.dateRange = []
queryParams.end_time = val[1] queryParams.page_no = 1
} else { getList()
delete queryParams.start_time }
delete queryParams.end_time
} const handleTabChange = () => {
queryParams.page_no = 1 queryParams.page_no = 1
getList() getList()
} }
+40 -4
View File
@@ -1,8 +1,27 @@
<template> <template>
<div class="asset-user-container"> <div class="asset-user-container">
<el-card shadow="never" class="!border-none"> <!-- 搜索区域 -->
<el-card class="!border-none" shadow="never">
<el-form class="ls-form" :model="searchData" inline>
<el-form-item class="w-[280px]" label="手机号">
<el-input
placeholder="请输入手机号"
v-model="searchData.phone"
clearable
@keyup.enter="handleSearch"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 列表区域 -->
<el-card class="!border-none mt-4" shadow="never">
<div class="mb-4"> <div class="mb-4">
<el-button type="primary" @click="handleAdd">新增分发账号</el-button> <el-button type="primary" @click="handleAdd">新增账号</el-button>
</div> </div>
<el-table :data="tableData" v-loading="loading"> <el-table :data="tableData" v-loading="loading">
@@ -65,7 +84,12 @@ import { apiAssetUserList, apiAssetUserAdd, apiAssetUserEdit, apiAssetUserDelete
const loading = ref(false) const loading = ref(false)
const tableData = ref([]) const tableData = ref([])
const total = ref(0) const total = ref(0)
const queryParams = reactive({
const searchData = reactive({
phone: ''
})
const queryParams = reactive<any>({
page_no: 1, page_no: 1,
page_size: 15 page_size: 15
}) })
@@ -89,7 +113,8 @@ const rules = {
const getList = async () => { const getList = async () => {
loading.value = true loading.value = true
try { try {
const res = await apiAssetUserList(queryParams) const params = { ...queryParams, ...searchData }
const res = await apiAssetUserList(params)
tableData.value = res.lists tableData.value = res.lists
total.value = res.count total.value = res.count
} catch (e) { } catch (e) {
@@ -99,6 +124,17 @@ const getList = async () => {
} }
} }
const handleSearch = () => {
queryParams.page_no = 1
getList()
}
const handleReset = () => {
searchData.phone = ''
queryParams.page_no = 1
getList()
}
const handleAdd = () => { const handleAdd = () => {
dialogTitle.value = '新增账号' dialogTitle.value = '新增账号'
Object.assign(formData, { id: '', phone: '', password: '', status: 1 }) Object.assign(formData, { id: '', phone: '', password: '', status: 1 })
@@ -16,6 +16,7 @@ class AssetResourceController extends BaseAdminController
$pageNo = $this->request->get('page_no', 1); $pageNo = $this->request->get('page_no', 1);
$pageSize = $this->request->get('page_size', 15); $pageSize = $this->request->get('page_size', 15);
$type = $this->request->get('type'); $type = $this->request->get('type');
$title = $this->request->get('title', '');
$startTime = $this->request->get('start_time'); $startTime = $this->request->get('start_time');
$endTime = $this->request->get('end_time'); $endTime = $this->request->get('end_time');
@@ -23,6 +24,9 @@ class AssetResourceController extends BaseAdminController
if ($type) { if ($type) {
$where[] = ['type', '=', $type]; $where[] = ['type', '=', $type];
} }
if ($title) {
$where[] = ['title', 'like', '%' . $title . '%'];
}
if ($startTime) { if ($startTime) {
$where[] = ['create_time', '>=', strtotime($startTime)]; $where[] = ['create_time', '>=', strtotime($startTime)];
} }
@@ -13,9 +13,16 @@ class AssetUserController extends BaseAdminController
{ {
$pageNo = $this->request->get('page_no', 1); $pageNo = $this->request->get('page_no', 1);
$pageSize = $this->request->get('page_size', 15); $pageSize = $this->request->get('page_size', 15);
$phone = $this->request->get('phone', '');
$count = AssetUser::count(); $where = [];
$lists = AssetUser::order('id', 'desc') if ($phone) {
$where[] = ['phone', 'like', '%' . $phone . '%'];
}
$count = AssetUser::where($where)->count();
$lists = AssetUser::where($where)
->order('id', 'desc')
->page($pageNo, $pageSize) ->page($pageNo, $pageSize)
->select(); ->select();