fix(v0.3.0): 框架内 peer 引用回退静态 import + 修 FieldRelativeTime 路径

- 覆盖颗粒度只在 3 个入口: router targets / module routes / field registry
- 框架内 .vue 之间互相引用全部硬编码静态 import,resolveVue/defineAsyncComponent 退出 .vue 文件
- 修 components/fields/FieldRelativeTime.vue 的 ../VueAdmin → ../../VueAdmin (移动后未跟改)
This commit is contained in:
2026-05-25 17:33:44 +08:00
parent 2b33bca681
commit de18412010
11 changed files with 37 additions and 46 deletions
+5 -2
View File
@@ -57,8 +57,11 @@ export interface ShrimpAdminOptions {
// ============== 源注册表 ==============
//
// 唯一约定:消费侧把 .vue 源放进 `sources`,框架按文件路径后缀解析。
// 框架内部对可覆盖的 .vue 也用 resolveVue 解析(而不是静态 import),保证 consumer 覆盖在框架内部使用点也生效。
// 框架在 3 个入口点用消费侧 sources 覆盖内置(按路径后缀同后缀覆盖):
// 1. router: components/{layout,login,404}.vue
// 2. registerRoute: module/<key>.vue 等业务模块
// 3. fieldRegistry: components/fields/Field<X>.vue (按文件名导出的字段类型)
// 框架内 .vue 之间的 peer 引用是硬编码静态 import,override 颗粒度就停在上面这些"入口"。
const internalSources = import.meta.glob<Component>('./{components,module}/**/*.vue')
const externalSources: Record<string, VueLoader> = {}
+6 -7
View File
@@ -78,22 +78,21 @@
</template>
<script lang="ts" setup>
import { defineAsyncComponent, ref, computed, useSlots, onMounted, type Component } from 'vue'
import { ref, computed, useSlots, onMounted, type Component } from 'vue'
import { ITableCrudProto, IFieldConfig, IModuleInfo, IPageQuery } from '../IShrimpType'
import { vueAdmin, resolveVue } from '../VueAdmin'
import { vueAdmin } from '../VueAdmin'
import { Plus, Delete as DeleteIcon, Download, Upload, Edit, VideoPlay, VideoPause, Operation } from '@element-plus/icons-vue'
import * as ElIcons from '@element-plus/icons-vue'
import { ElMessageBox, ElMessage } from 'element-plus'
import { useI18n } from 'vue-i18n'
import { useRoute, useRouter } from 'vue-router'
import { useTableUrlSync } from '../composables/useTableUrlSync'
import ShrimpEditDrawer from './ShrimpEditDrawer.vue'
import ShrimpFilterDrawer from './ShrimpFilterDrawer.vue'
import ShrimpSearchInput from './ShrimpSearchInput.vue'
import ShrimpFilterTrigger from './ShrimpFilterTrigger.vue'
import * as XLSX from 'xlsx'
const ShrimpEditDrawer = defineAsyncComponent(resolveVue('components/ShrimpEditDrawer.vue'))
const ShrimpFilterDrawer = defineAsyncComponent(resolveVue('components/ShrimpFilterDrawer.vue'))
const ShrimpSearchInput = defineAsyncComponent(resolveVue('components/ShrimpSearchInput.vue'))
const ShrimpFilterTrigger = defineAsyncComponent(resolveVue('components/ShrimpFilterTrigger.vue'))
const { t } = useI18n()
interface Props {
+1 -1
View File
@@ -10,7 +10,7 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { vueAdmin } from '../VueAdmin'
import { vueAdmin } from '../../VueAdmin'
const { t } = useI18n()
+7 -8
View File
@@ -43,15 +43,14 @@
</template>
<script lang="ts" setup>
import { defineAsyncComponent, ref, watch } from "vue";
import { vueAdmin, resolveVue } from "../VueAdmin";
import { ref, watch } from "vue";
import { vueAdmin } from "../VueAdmin";
import { type IMenuItem } from "../IShrimpType";
const SideM = defineAsyncComponent(resolveVue('components/sideM.vue'));
const navMenu = defineAsyncComponent(resolveVue('components/navMenu.vue'));
const Topbar = defineAsyncComponent(resolveVue('components/topbar.vue'));
const Userbar = defineAsyncComponent(resolveVue('components/userbar.vue'));
const Logo = defineAsyncComponent(resolveVue('components/logo.vue'));
import SideM from "./sideM.vue";
import navMenu from "./navMenu.vue";
import Topbar from "./topbar.vue";
import Userbar from "./userbar.vue";
import Logo from "./logo.vue";
// 初始化选中菜单
let currentPath = vueAdmin.router.currentRoute.value.path;
+3 -4
View File
@@ -30,11 +30,10 @@
</template>
<script lang="ts" setup>
import { vueAdmin, resolveVue } from "../VueAdmin";
import { defineAsyncComponent, reactive, computed, onMounted } from "vue";
import { vueAdmin } from "../VueAdmin";
import { reactive, computed, onMounted } from "vue";
import { useI18n } from "vue-i18n";
const LangSwitch = defineAsyncComponent(resolveVue('components/ShrimpLangSwitch.vue'));
import LangSwitch from "./ShrimpLangSwitch.vue";
vueAdmin.token = null;
+4 -5
View File
@@ -33,11 +33,10 @@
</template>
<script lang="ts" setup>
import { defineAsyncComponent, ref } from "vue";
import { vueAdmin, resolveVue } from '../VueAdmin';
const navMenu = defineAsyncComponent(resolveVue('components/navMenu.vue'));
const Logo = defineAsyncComponent(resolveVue('components/logo.vue'));
import { ref } from "vue";
import { vueAdmin } from '../VueAdmin';
import navMenu from "./navMenu.vue";
import Logo from "./logo.vue";
let nav = ref(false);
function showMobileNav() { nav.value = true; }
+2 -4
View File
@@ -20,10 +20,8 @@
</template>
<script lang="ts" setup>
import { vueAdmin, resolveVue } from "../VueAdmin";
import { defineAsyncComponent } from "vue";
const LangSwitch = defineAsyncComponent(resolveVue('components/ShrimpLangSwitch.vue'));
import { vueAdmin } from "../VueAdmin";
import LangSwitch from "./ShrimpLangSwitch.vue";
function screen() {
vueAdmin.fullscreen();
+1 -2
View File
@@ -60,8 +60,7 @@ export {
} from './ShrimpClient'
// 框架组件 — 业务页面想直接复用就 import 这些。
// 注意:这些是「静态」导出,直接 import 拿到的就是框架内置版本,不会被消费侧 sources 覆盖。
// 要让 consumer 覆盖在所有引用点都生效,框架内部已统一改用 resolveVue 动态解析。
// 这些是「静态」导出,拿到的就是框架内置版本,不受消费侧 sources 影响。
export { default as ShrimpTable } from './components/ShrimpTable.vue'
export { default as ShrimpEditDrawer } from './components/ShrimpEditDrawer.vue'
export { default as ShrimpFilterDrawer } from './components/ShrimpFilterDrawer.vue'
+3 -4
View File
@@ -48,13 +48,12 @@
</template>
<script lang="ts" setup>
import { defineAsyncComponent, ref, onMounted } from 'vue'
import { ref, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { vueAdmin, resolveVue } from '../VueAdmin'
import { vueAdmin } from '../VueAdmin'
import { IRole, IRoleProto, WithId, ILabel } from '../IShrimpType'
import { ElMessage } from 'element-plus'
const ShrimpPowerTree = defineAsyncComponent(resolveVue('components/ShrimpPowerTree.vue'))
import ShrimpPowerTree from '../components/ShrimpPowerTree.vue'
interface IPowerItem {
key: string
+2 -5
View File
@@ -7,11 +7,8 @@
</template>
<script lang="ts" setup>
import { defineAsyncComponent } from 'vue'
import { resolveVue } from '../VueAdmin'
const ShrimpTable = defineAsyncComponent(resolveVue('components/ShrimpTable.vue'))
const FieldRelativeTime = defineAsyncComponent(resolveVue('components/fields/FieldRelativeTime.vue'))
import ShrimpTable from '../components/ShrimpTable.vue'
import FieldRelativeTime from '../components/fields/FieldRelativeTime.vue'
</script>
<style scoped>
+3 -4
View File
@@ -11,12 +11,11 @@
</template>
<script lang="ts" setup>
import { defineAsyncComponent, ref, computed, onMounted, watch } from 'vue'
import { ref, computed, onMounted, watch } from 'vue'
import { useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { vueAdmin, resolveVue } from '../../VueAdmin'
const ShrimpTable = defineAsyncComponent(resolveVue('components/ShrimpTable.vue'))
import { vueAdmin } from '../../VueAdmin'
import ShrimpTable from '../../components/ShrimpTable.vue'
const route = useRoute()
const { t } = useI18n()