Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b0887b126 | ||
|
|
bba08dadcc | ||
|
|
701ed957ef | ||
|
|
0b75f8c6f2 |
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "shrimp-admin",
|
||||
"version": "0.3.4",
|
||||
"version": "0.3.8",
|
||||
"private": true,
|
||||
"description": "Shrimp 框架前端 — 消费 ShrimpServer + ShrimpTable 契约的经典 Vue3 + Element Plus 实现",
|
||||
"main": "src/index.ts",
|
||||
|
||||
@@ -132,8 +132,18 @@ const {
|
||||
|
||||
const searchVisible = ref(false)
|
||||
|
||||
// relation 跳转用 ?filter={_id} 锁定单条;_id 是隐形 pin(不在筛选抽屉里),
|
||||
// 用户一旦搜索/改筛选就清掉它,避免被看不见的 _id 一直 AND 着导致结果莫名为空
|
||||
function stripJumpPin() {
|
||||
if ('_id' in filterData.value) {
|
||||
const { _id, ...rest } = filterData.value
|
||||
filterData.value = rest
|
||||
}
|
||||
}
|
||||
|
||||
function onSearch() {
|
||||
searchKeyword.value = keyword.value
|
||||
stripJumpPin()
|
||||
currentPage.value = 1
|
||||
refresh()
|
||||
}
|
||||
@@ -151,7 +161,8 @@ const hasFilter = computed(() => {
|
||||
})
|
||||
|
||||
async function handleFilterConfirm(newFilterData: Record<string, any>) {
|
||||
filterData.value = newFilterData
|
||||
const { _id, ...rest } = newFilterData // 确认筛选 → 丢弃跳转 pin
|
||||
filterData.value = rest
|
||||
currentPage.value = 1
|
||||
await refresh()
|
||||
}
|
||||
@@ -323,8 +334,10 @@ async function handleSave() {
|
||||
formFields.value.forEach(field => {
|
||||
if (field.editable === 'readonly') return
|
||||
if (field.editable === 'addOnly') return
|
||||
const newValue = formData.value[field.key]
|
||||
const oldValue = originalData.value[field.key]
|
||||
// 清空字段值为 undefined 时,JSON.stringify 会丢键 → 后端收不到、看似"提交无效"。
|
||||
// 归一成 null:既保证清空能提交(后端置空),又让"两边都空"不误判为有改动。
|
||||
const newValue = formData.value[field.key] ?? null
|
||||
const oldValue = originalData.value[field.key] ?? null
|
||||
if (newValue === oldValue) return
|
||||
submitData[field.key] = newValue
|
||||
})
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
style="width: 100%"
|
||||
/>
|
||||
<el-date-picker v-else :model-value="modelValue" @update:model-value="$emit('update:modelValue', $event)" :disabled="disabled"
|
||||
type="datetime" style="width: 100%" />
|
||||
type="datetime" :clearable="!field.required" style="width: 100%" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
>
|
||||
<el-option v-for="opt in options" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
<el-select v-else :model-value="stringValue" @update:model-value="$emit('update:modelValue', $event)" :disabled="disabled" :multiple="field.multiple" filterable remote :remote-method="onSearch" :loading="loading" style="width: 100%">
|
||||
<el-select v-else :model-value="stringValue" @update:model-value="onEdit" :disabled="disabled" :multiple="field.multiple" :clearable="!field.required" filterable remote :remote-method="onSearch" :loading="loading" style="width: 100%">
|
||||
<el-option v-for="opt in options" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||
</el-select>
|
||||
</template>
|
||||
@@ -35,10 +35,16 @@ const props = defineProps<{
|
||||
disabled?: boolean
|
||||
}>()
|
||||
|
||||
defineEmits<{
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: any]
|
||||
}>()
|
||||
|
||||
// 编辑态清空:el-select 单选清空发 '' 或 undefined,relation 是 ObjectId、且 undefined 会被
|
||||
// JSON.stringify 丢键 → 都归一成 null(取消关联)。多选清空是 [],原样。
|
||||
function onEdit(v: any) {
|
||||
emit('update:modelValue', v === '' || v == null ? (props.field.multiple ? [] : null) : v)
|
||||
}
|
||||
|
||||
const options = ref<{ label: string; value: string }[]>([])
|
||||
const loading = ref(false)
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
@update:model-value="$emit('update:modelValue', $event)"
|
||||
:disabled="disabled"
|
||||
:multiple="field.multiple"
|
||||
:clearable="!field.required"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option v-for="opt in resolvedOptions" :key="opt.value" :label="vueAdmin.t(opt.label)" :value="opt.value" />
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</el-tag>
|
||||
<el-input v-model="inputValue" @keyup.enter="addTag" @blur="addTag" :placeholder="$t('base.pressEnter')" />
|
||||
</div>
|
||||
<el-input v-else :model-value="modelValue" @update:model-value="$emit('update:modelValue', $event)" :disabled="disabled" clearable />
|
||||
<el-input v-else :model-value="modelValue" @update:model-value="$emit('update:modelValue', $event)" :disabled="disabled" :clearable="!field.required" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
:model-value="modelValue"
|
||||
@update:model-value="$emit('update:modelValue', $event)"
|
||||
:disabled="disabled"
|
||||
clearable
|
||||
:clearable="!field.required"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
||||
+17
-1
@@ -50,6 +50,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { vueAdmin } from '../VueAdmin'
|
||||
import { IRole, IRoleProto, WithId, ILabel } from '../IShrimpType'
|
||||
import { ElMessage } from 'element-plus'
|
||||
@@ -61,12 +62,24 @@ interface IPowerItem {
|
||||
}
|
||||
|
||||
const { t } = useI18n()
|
||||
const route = useRoute()
|
||||
|
||||
const props = defineProps<{
|
||||
moduleKey: string
|
||||
events?: string[]
|
||||
}>()
|
||||
|
||||
// relation 跳转落到 role 页时带 ?filter={"_id":...}。role 是自定义 master-detail 页(非 ShrimpTable、
|
||||
// 不做服务端过滤),全量加载后按这个 _id 在列表里选中那条;解析不出就走默认(选第一个)。
|
||||
function jumpTargetId(): string {
|
||||
try {
|
||||
const f = route.query.filter ? JSON.parse(String(route.query.filter)) : null
|
||||
return f && typeof f === 'object' ? String(f._id || '') : ''
|
||||
} catch {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
const roleApi = vueAdmin.getModule<IRoleProto>('role')
|
||||
|
||||
const roleList = ref<WithId<IRole>[]>([])
|
||||
@@ -138,7 +151,10 @@ async function handleDelete() {
|
||||
onMounted(async () => {
|
||||
allPowers.value = await roleApi.allPower()
|
||||
await loadRoles()
|
||||
if (roleList.value.length > 0) {
|
||||
const jumpId = jumpTargetId()
|
||||
if (jumpId && roleList.value.some(r => r._id === jumpId)) {
|
||||
onSelect(jumpId)
|
||||
} else if (roleList.value.length > 0) {
|
||||
onSelect(roleList.value[0]._id)
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user