demo: 加 Vue 前端到 examples/basic-admin/web
为了端到端验证 Shrimp 框架,把 hand-admin 前端拷进 examples/basic-admin/web
作为临时演示用前端,@shrimp alias 直接指向同仓 src/,免构建。
修改要点:
- web/vite.config.ts: @shrimp 改成 ../../../src; proxy /admin-api 到 :3100
- web/tsconfig.json: 同步 @shrimp 路径; 删掉 hand-server-2 的 paths
- web/src/locales: 删掉 matter_*/zerobase 业务 key
- web/src/module: 删掉 matter_*/zerobase 业务 vue,只留 user/role/FieldRelativeTime
- examples/basic-admin/index.ts:
- mount 到 /admin-api/* 而不是 /api/*
- 加 /config /login /me 端点 (mock super-admin operator,固定 token)
- DemoShrimp 子类覆盖 getMenuTree 用模块自身 label
- MemoryShrimpCrud 的 getRelatedCrud 手动 wire 到 crudRegistry,
populate 才能跑 (后续 70→90 改进项)
curl 已验证 /config /login /me /product/list 全通,tagIds_label 正确旁挂。
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
import { ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
export interface UseTableUrlSyncOptions {
|
||||
pageSize: number
|
||||
}
|
||||
|
||||
export function useTableUrlSync(options: UseTableUrlSyncOptions) {
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
|
||||
const currentPage = ref(1)
|
||||
const currentPageSize = ref(options.pageSize)
|
||||
const keyword = ref('')
|
||||
const searchKeyword = ref('')
|
||||
const currentSortBy = ref('')
|
||||
const currentSortOrder = ref<'asc' | 'desc'>('asc')
|
||||
const filterData = ref<Record<string, any>>({})
|
||||
|
||||
function restoreFromQuery() {
|
||||
const q = route.query
|
||||
if (q.page) currentPage.value = Number(q.page) || 1
|
||||
if (q.pageSize) currentPageSize.value = Number(q.pageSize) || options.pageSize
|
||||
if (q.keyword) {
|
||||
keyword.value = String(q.keyword)
|
||||
searchKeyword.value = String(q.keyword)
|
||||
}
|
||||
if (q.sortBy) currentSortBy.value = String(q.sortBy)
|
||||
if (q.sortOrder && (q.sortOrder === 'asc' || q.sortOrder === 'desc')) {
|
||||
currentSortOrder.value = q.sortOrder
|
||||
}
|
||||
if (q.filter) {
|
||||
try {
|
||||
const parsed = JSON.parse(String(q.filter))
|
||||
if (typeof parsed === 'object' && parsed !== null) {
|
||||
filterData.value = parsed
|
||||
}
|
||||
} catch { /* ignore invalid JSON */ }
|
||||
}
|
||||
}
|
||||
|
||||
// 表格自身管理的 query key,sync 时只覆盖这几个,其它保留(如 ?id= 子表父记录、自定义参数)
|
||||
const TABLE_QUERY_KEYS = ['page', 'pageSize', 'keyword', 'sortBy', 'sortOrder', 'filter']
|
||||
|
||||
function syncToQuery() {
|
||||
const preserved: Record<string, any> = {}
|
||||
for (const [k, v] of Object.entries(route.query)) {
|
||||
if (!TABLE_QUERY_KEYS.includes(k)) preserved[k] = v
|
||||
}
|
||||
const query: Record<string, any> = { ...preserved }
|
||||
if (currentPage.value > 1) query.page = String(currentPage.value)
|
||||
if (currentPageSize.value !== options.pageSize) query.pageSize = String(currentPageSize.value)
|
||||
if (searchKeyword.value) query.keyword = searchKeyword.value
|
||||
if (currentSortBy.value) {
|
||||
query.sortBy = currentSortBy.value
|
||||
query.sortOrder = currentSortOrder.value
|
||||
}
|
||||
const cleanFilter: Record<string, any> = {}
|
||||
for (const [key, val] of Object.entries(filterData.value)) {
|
||||
if (val === '' || val === null || val === undefined) continue
|
||||
if (Array.isArray(val) && val.length === 0) continue
|
||||
cleanFilter[key] = val
|
||||
}
|
||||
if (Object.keys(cleanFilter).length > 0) {
|
||||
query.filter = JSON.stringify(cleanFilter)
|
||||
}
|
||||
router.replace({ query })
|
||||
}
|
||||
|
||||
let isRestoring = false
|
||||
|
||||
watch(
|
||||
[currentPage, currentPageSize, searchKeyword, currentSortBy, currentSortOrder, filterData],
|
||||
() => {
|
||||
if (!isRestoring) {
|
||||
syncToQuery()
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
function restore() {
|
||||
isRestoring = true
|
||||
restoreFromQuery()
|
||||
isRestoring = false
|
||||
}
|
||||
|
||||
return {
|
||||
currentPage,
|
||||
currentPageSize,
|
||||
keyword,
|
||||
searchKeyword,
|
||||
currentSortBy,
|
||||
currentSortOrder,
|
||||
filterData,
|
||||
restore,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user