304 lines
7.6 KiB
Plaintext
304 lines
7.6 KiB
Plaintext
<template>
|
||
<view class="user-management-page">
|
||
<text class="page-title">{{ $t('user_mgmt.title') }}</text>
|
||
<view class="search-bar">
|
||
<input class="searchinput" type="text" v-model="searchQuery" placeholder="Search users..." />
|
||
<button class="searchbutton" @click="searchUsers">{{ $t('common.search') }}</button>
|
||
</view>
|
||
<supadb
|
||
ref="userdb"
|
||
:collection="'ak_users'"
|
||
:field="'*'"
|
||
:filter="where"
|
||
:orderby="'id.desc'"
|
||
:page-size="pageSize"
|
||
:page-current="pageCurrent"
|
||
getcount="exact"
|
||
loadtime="manual"
|
||
v-slot:default="{ data, pagination, loading, current, total, error }"
|
||
@load="onUserLoad"
|
||
>
|
||
<view v-if="loading">{{ $t('common.loading') }}</view>
|
||
<view v-else-if="error">{{ error }}</view>
|
||
<view v-else>
|
||
<!-- Large Screen Layout (Table) -->
|
||
<view class="table-view">
|
||
<view class="table-header">
|
||
<text>{{ $t('user.username') }}</text>
|
||
<text>{{ $t('user.email') }}</text>
|
||
<text>{{ $t('user.role') }}</text>
|
||
<text>{{ $t('user.created_at') }}</text>
|
||
<text>{{ $t('common.action') }}</text>
|
||
</view>
|
||
<view v-for="(user, idx) in (data as Array<UTSJSONObject>)" :key="user.get('id')" :class="['table-row', idx % 2 === 0 ? 'row-even' : 'row-odd']">
|
||
<text>{{ user.get('username') }}</text>
|
||
<text>{{ user.get('email') }}</text>
|
||
<text>{{ user.get('role') }}</text>
|
||
<text>{{ user.get('created_at') }}</text>
|
||
<view class="action-buttons">
|
||
<button @click="editUser(user)">{{ $t('common.edit') }}</button>
|
||
<button @click="deleteUser(user)">{{ $t('common.delete') }}</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- Small Screen Layout (Cards) -->
|
||
<view class="card-view">
|
||
<view v-for="(user, idx) in (data as Array<UTSJSONObject>)" :key="user.get('id')" :class="['user-card', idx % 2 === 0 ? 'row-even' : 'row-odd']">
|
||
<view class="card-row">
|
||
<text class="card-label">{{ $t('user.username') }}:</text>
|
||
<text class="card-value">{{ user.get('username') }}</text>
|
||
</view>
|
||
<view class="card-row">
|
||
<text class="card-label">{{ $t('user.email') }}:</text>
|
||
<text class="card-value">{{ user.get('email') }}</text>
|
||
</view>
|
||
<view class="card-row">
|
||
<text class="card-label">{{ $t('user.role') }}:</text>
|
||
<text class="card-value">{{ user.get('role') }}</text>
|
||
</view>
|
||
<view class="card-row">
|
||
<text class="card-label">{{ $t('user.created_at') }}:</text>
|
||
<text class="card-value">{{ user.get('created_at') }}</text>
|
||
</view>
|
||
<view class="card-actions">
|
||
<button @click="editUser(user)">{{ $t('common.edit') }}</button>
|
||
<button @click="deleteUser(user)">{{ $t('common.delete') }}</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="pagination">
|
||
<button @click="prevPage(pagination!!)">{{ $t('common.prev') }}</button>
|
||
<text>{{ current}}/{{ total }}</text>
|
||
<button @click="nextPage(pagination!!)">{{ $t('common.next') }}</button>
|
||
<button v-if="hasMoreData" @click="continueIteration()">{{ $t('common.continueToIterate') }}</button>
|
||
</view>
|
||
</view>
|
||
</supadb>
|
||
<!-- 编辑/新增弹窗等可后续补充 -->
|
||
</view>
|
||
</template>
|
||
<script lang="uts">
|
||
import supa from '@/components/supadb/aksupainstance.uts';
|
||
|
||
|
||
export default {
|
||
name: 'UserManagement',
|
||
data() {
|
||
return {
|
||
supadb: null as SupadbComponentPublicInstance | null,
|
||
where: {},
|
||
pageSize: 10,
|
||
pageCurrent: 1,
|
||
searchQuery: '',
|
||
screenWidth: uni.getSystemInfoSync().windowWidth,
|
||
hasMoreData: false
|
||
}
|
||
},
|
||
onReady() {
|
||
this.supadb = this.$refs["userdb"] as SupadbComponentPublicInstance;
|
||
// supa.from('system_dept').select(*).or('"name.like.%20%,email.like.%202%");
|
||
this.supadb?.loadData?.({ clear: false })
|
||
|
||
},
|
||
methods: {
|
||
onUserLoad(data: any[]) {
|
||
// 可处理数<E79086>?
|
||
this.hasMoreData = data.length === this.pageSize;
|
||
},
|
||
async prevPage(pagination: any) {
|
||
this.pageCurrent--;
|
||
await nextTick();
|
||
this.supadb?.loadData?.({ clear: false })
|
||
},
|
||
async nextPage(pagination: any) {
|
||
this.pageCurrent++;
|
||
await nextTick();
|
||
this.supadb?.loadData?.({ clear: false })
|
||
},
|
||
editUser(user: UTSJSONObject) {
|
||
// 编辑逻辑
|
||
console.log(user)
|
||
uni.navigateTo({
|
||
url:'/pages/admins/users/detail?id='+ user.getString("id")
|
||
})
|
||
},
|
||
deleteUser(user: any) {
|
||
// 删除逻辑
|
||
},
|
||
async searchUsers() {
|
||
// Implement search logic
|
||
if (this.searchQuery!=null) {
|
||
// this.where = {
|
||
// text: this.searchQuery,
|
||
// column: ['username', 'email', 'role']
|
||
// };
|
||
// this.where = { email: { ilike: '%'+this.searchQuery+'%' }} as UTSJSONObject
|
||
this.where ={ or:"username.like.%"+this.searchQuery+"%,email.like.%"+this.searchQuery+"%"}
|
||
} else {
|
||
this.where = {};
|
||
}
|
||
console.log(this.where)
|
||
this.pageCurrent = 1;
|
||
await nextTick();
|
||
this.supadb?.loadData?.({ clear: true });
|
||
},
|
||
async continueIteration() {
|
||
this.pageCurrent++;
|
||
await nextTick();
|
||
this.supadb?.loadData?.({ clear: false })
|
||
}
|
||
},
|
||
onResize(size) {
|
||
// 这里处理页面尺寸变化
|
||
this.screenWidth = size.size.windowWidth;
|
||
|
||
}
|
||
}
|
||
</script>
|
||
<style scoped>
|
||
.user-management-page {
|
||
padding: 20px;
|
||
}
|
||
|
||
.search-bar {
|
||
display: flex;
|
||
margin-bottom: 16px;
|
||
padding: 8px;
|
||
}
|
||
|
||
/* Table View (Large Screens) */
|
||
.table-view {
|
||
display: flex;
|
||
flex-direction: column;
|
||
width: 100%;
|
||
}
|
||
|
||
.table-header, .table-row {
|
||
display: flex;
|
||
width: 100%;
|
||
padding: 16px;
|
||
align-items: center;
|
||
flex-direction: row;
|
||
}
|
||
|
||
.table-header {
|
||
font-weight: bold;
|
||
padding-bottom: 8px;
|
||
border-bottom: 1px solid #ccc;
|
||
}
|
||
|
||
.table-header text, .table-row text {
|
||
flex: 1;
|
||
padding: 8px 4px;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.table-row {
|
||
border-bottom: 1px solid #eee;
|
||
padding: 8px 0;
|
||
}
|
||
|
||
.table-row:nth-child(even) {
|
||
background-color: #f7f7fa;
|
||
}
|
||
.table-row:nth-child(odd) {
|
||
background-color: #fff;
|
||
}
|
||
|
||
.action-buttons {
|
||
display: flex;
|
||
padding: 8px;
|
||
}
|
||
|
||
/* Card View (Small Screens) */
|
||
.card-view {
|
||
display: none;
|
||
flex-direction: column;
|
||
width: 100%;
|
||
padding: 16px;
|
||
}
|
||
|
||
.user-card {
|
||
border: 1px solid #eee;
|
||
border-radius: 8px;
|
||
padding: 16px;
|
||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.user-card:nth-child(even) {
|
||
background-color: #f7f7fa;
|
||
}
|
||
.user-card:nth-child(odd) {
|
||
background-color: #fff;
|
||
}
|
||
|
||
.card-row {
|
||
display: flex;
|
||
padding: 4px 0;
|
||
}
|
||
|
||
.card-label {
|
||
font-weight: bold;
|
||
width: 100px;
|
||
}
|
||
|
||
.card-value {
|
||
flex: 1;
|
||
}
|
||
|
||
.card-actions {
|
||
display: flex;
|
||
padding: 8px;
|
||
margin-top: 12px;
|
||
/* justify-content: flex-end; */
|
||
}
|
||
|
||
.pagination {
|
||
margin-top: 16px;
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 16px;
|
||
justify-content: center;
|
||
}
|
||
|
||
/* Responsive Design */
|
||
@media screen and (max-width: 768px) {
|
||
.table-view {
|
||
display: none;
|
||
}
|
||
|
||
.card-view {
|
||
display: flex;
|
||
}
|
||
|
||
.search-bar {
|
||
flex-direction: row;
|
||
justify-content: flex-end;
|
||
}
|
||
}
|
||
|
||
@media screen and (min-width: 769px) {
|
||
.table-view {
|
||
display: flex;
|
||
}
|
||
|
||
.card-view {
|
||
display: none;
|
||
}
|
||
}
|
||
|
||
.row-even { background-color: #f7f7fa; }
|
||
.row-odd { background-color: #fff; }
|
||
.searchbutton{
|
||
width:200rpx;
|
||
height:80rpx;
|
||
}
|
||
.searchinput{
|
||
flex:1;
|
||
}
|
||
</style>
|