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>
<div class="asset-resource-container">
<el-card shadow="never" class="!border-none">
<div class="mb-4 flex items-center gap-4 flex-wrap">
<el-button type="primary" @click="handleAdd">上传并分发资源</el-button>
<el-date-picker
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
@change="handleDateChange"
clearable
style="width: 300px;"
/>
<!-- 搜索区域 -->
<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.title"
clearable
@keyup.enter="handleSearch"
/>
</el-form-item>
<el-form-item label="上传时间">
<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>
<el-tabs v-model="queryParams.type" @tab-change="handleTabChange">
@@ -24,14 +44,14 @@
<el-table :data="tableData" v-loading="loading">
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="title" label="标题" />
<el-table-column label="预览">
<el-table-column prop="title" label="标题" min-width="150" />
<el-table-column label="预览" width="100">
<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-link v-else :href="row.file_url" target="_blank" type="primary">点击预览</el-link>
</template>
</el-table-column>
<el-table-column label="关联账号" show-overflow-tooltip>
<el-table-column label="关联账号" min-width="150" show-overflow-tooltip>
<template #default="{ row }">
<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>
@@ -58,9 +78,9 @@
</div>
</el-card>
<!-- 新增资源弹窗 -->
<!-- 新增/编辑资源弹窗 -->
<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-radio-group v-model="formData.type">
<el-radio :label="1">图片</el-radio>
@@ -99,7 +119,7 @@
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { apiAssetResourceList, apiAssetResourceAdd, apiAssetResourceEdit, apiAssetResourceDelete, apiAssetUserList } from '@/api/asset'
import MaterialPicker from '@/components/material/picker.vue'
@@ -108,7 +128,12 @@ import Upload from '@/components/upload/index.vue'
const loading = ref(false)
const tableData = ref([])
const total = ref(0)
const dateRange = ref<string[]>([])
const searchData = reactive<any>({
title: '',
dateRange: []
})
const queryParams = reactive<any>({
type: '1',
page_no: 1,
@@ -131,15 +156,34 @@ const formData = reactive<any>({
user_ids: []
})
const rules = {
title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
file_url: [{ required: true, message: '请输入或上传文件获取链接', trigger: 'blur' }]
const computedRules = computed(() => {
if (isEdit.value) {
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 () => {
loading.value = true
try {
const res = await apiAssetResourceList(queryParams)
const res = await apiAssetResourceList(buildQueryParams())
tableData.value = res.lists
total.value = res.count
} catch (e) {
@@ -158,19 +202,19 @@ const fetchUserOptions = async () => {
}
}
const handleTabChange = () => {
const handleSearch = () => {
queryParams.page_no = 1
getList()
}
const handleDateChange = (val: string[] | null) => {
if (val && val.length === 2) {
queryParams.start_time = val[0]
queryParams.end_time = val[1]
} else {
delete queryParams.start_time
delete queryParams.end_time
}
const handleReset = () => {
searchData.title = ''
searchData.dateRange = []
queryParams.page_no = 1
getList()
}
const handleTabChange = () => {
queryParams.page_no = 1
getList()
}
+40 -4
View File
@@ -1,8 +1,27 @@
<template>
<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">
<el-button type="primary" @click="handleAdd">新增分发账号</el-button>
<el-button type="primary" @click="handleAdd">新增账号</el-button>
</div>
<el-table :data="tableData" v-loading="loading">
@@ -65,7 +84,12 @@ import { apiAssetUserList, apiAssetUserAdd, apiAssetUserEdit, apiAssetUserDelete
const loading = ref(false)
const tableData = ref([])
const total = ref(0)
const queryParams = reactive({
const searchData = reactive({
phone: ''
})
const queryParams = reactive<any>({
page_no: 1,
page_size: 15
})
@@ -89,7 +113,8 @@ const rules = {
const getList = async () => {
loading.value = true
try {
const res = await apiAssetUserList(queryParams)
const params = { ...queryParams, ...searchData }
const res = await apiAssetUserList(params)
tableData.value = res.lists
total.value = res.count
} 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 = () => {
dialogTitle.value = '新增账号'
Object.assign(formData, { id: '', phone: '', password: '', status: 1 })
@@ -16,6 +16,7 @@ class AssetResourceController extends BaseAdminController
$pageNo = $this->request->get('page_no', 1);
$pageSize = $this->request->get('page_size', 15);
$type = $this->request->get('type');
$title = $this->request->get('title', '');
$startTime = $this->request->get('start_time');
$endTime = $this->request->get('end_time');
@@ -23,6 +24,9 @@ class AssetResourceController extends BaseAdminController
if ($type) {
$where[] = ['type', '=', $type];
}
if ($title) {
$where[] = ['title', 'like', '%' . $title . '%'];
}
if ($startTime) {
$where[] = ['create_time', '>=', strtotime($startTime)];
}
@@ -13,9 +13,16 @@ class AssetUserController extends BaseAdminController
{
$pageNo = $this->request->get('page_no', 1);
$pageSize = $this->request->get('page_size', 15);
$phone = $this->request->get('phone', '');
$count = AssetUser::count();
$lists = AssetUser::order('id', 'desc')
$where = [];
if ($phone) {
$where[] = ['phone', 'like', '%' . $phone . '%'];
}
$count = AssetUser::where($where)->count();
$lists = AssetUser::where($where)
->order('id', 'desc')
->page($pageNo, $pageSize)
->select();