feat: 迁移 Vue3 + Vite + view-ui-plus(对齐 NoticeFront 框架)

- 构建:Vue CLI 4 → Vite 5,入口迁至根 index.html(含 env-config + 主题通道 loader)
- 技术栈:Vue 2.6 → Vue 3.4,view-design → view-ui-plus 1.3.24,vue-router 3 → 4(hash)
- 壳层重写:App.vue / components/layout.vue 对齐 Notice 骨架(logo-badge、icon-* 通道图标、resolveMenuPage、crumb-home 基线)
- 机械转换:具名 slot → template #x、.sync → v-model:、@click.native、$set、beforeDestroy、/deep/ → :deep()
- render:h('Button')/h('Input') → 真组件 + 扁平 props/onClick
- 组件适配:vuedraggable 4 的 #item 插槽;vue-treeselect → @zanmato/vue3-treeselect;Page 分页改 v-model + pageSize 显式回写
- 清理:删除 Vue2 死代码(layout_old/bak/child、App.Net、codeModal、未引用组件)
- 修复:深链接首次加载被重定向到首个模块(router.isReady)

验证:vite build 通过;headless CDP 全 15 路由无异常;教师列表 2 行渲染、操作列按钮点击弹窗正常。
This commit is contained in:
lijing
2026-10-20 15:16:52 +08:00
parent 0564f5f89d
commit 7e49587c10
73 changed files with 6083 additions and 33190 deletions
+36 -45
View File
@@ -11,24 +11,22 @@
<div class="btn-container">
<draggable
v-model="campuslist"
animation="150"
item-key="name"
:animation="150"
ghost-class="drag-ghost"
class="drag-box"
:options="{ group: 'people' }"
group="people"
@start="drag = true"
@end="drag = false"
:move="getdata1"
@update="datadragEnd1"
@change="datadragEnd1"
>
<div
v-for="(item, index) in campuslist"
:key="index"
class="tag-wrap"
@dblclick="openEditModal('campus', index)"
>
<div class="tag-btn">{{ item.name }}</div>
<span class="close-btn" @click.stop="delCampus(index)">×</span>
</div>
<template #item="{ element, index }">
<div class="tag-wrap" @dblclick="openEditModal('campus', index)">
<div class="tag-btn">{{ element.name }}</div>
<span class="close-btn" @click.stop="delCampus(index)">×</span>
</div>
</template>
</draggable>
<Button icon="ios-add" size="large" class="add-btn" @click="openAddModal('campus')">添加校区</Button>
</div>
@@ -43,24 +41,22 @@
<div class="btn-container">
<draggable
v-model="divisionlist"
animation="150"
item-key="name"
:animation="150"
ghost-class="drag-ghost"
class="drag-box"
:options="{ group: 'people' }"
group="people"
@start="drag = true"
@end="drag = false"
:move="getdata2"
@update="datadragEnd2"
@change="datadragEnd2"
>
<div
v-for="(item, index) in divisionlist"
:key="index"
class="tag-wrap"
@dblclick="openEditModal('dept', index)"
>
<div class="tag-btn">{{ item.name }}</div>
<span class="close-btn" @click.stop="delDept(index)">×</span>
</div>
<template #item="{ element, index }">
<div class="tag-wrap" @dblclick="openEditModal('dept', index)">
<div class="tag-btn">{{ element.name }}</div>
<span class="close-btn" @click.stop="delDept(index)">×</span>
</div>
</template>
</draggable>
<Button icon="ios-add" size="large" class="add-btn" @click="openAddModal('dept')">添加系部</Button>
</div>
@@ -80,7 +76,7 @@
placeholder="输入代码或名称搜索"
@keyup.enter="searchMajor"
>
<Icon slot="suffix" type="ios-search" @click="searchMajor" style="cursor:pointer;"></Icon>
<template #suffix><Icon type="ios-search" @click="searchMajor" style="cursor:pointer;"></Icon></template>
</i-Input>
</div>
</div>
@@ -98,7 +94,7 @@
<!-- <div class="pagination-fixed-bottom">
<span class="total-desc">共 {{ majorTotal }} 条</span>
<Page
:current.sync="majorPageNum"
v-model="majorPageNum"
:total="majorTotal"
:page-size="majorPageSize"
:page-size-opts="[10,20,50]"
@@ -111,7 +107,7 @@
<!-- 校区/系部 新增编辑弹窗 -->
<Modal v-model="modalVisible" :title="modalTitle" width="420">
<Form ref="formRef" :model="formData" :rules="formRule" label-width="90">
<Form ref="formRef" :model="formData" :rules="formRule" :label-width="90">
<FormItem label="校区名称" v-if="modalType === 'campus'" prop="name">
<Input v-model="formData.name" placeholder="请输入校区名称" />
</FormItem>
@@ -119,15 +115,15 @@
<Input v-model="formData.name" placeholder="请输入系部名称" />
</FormItem>
</Form>
<div slot="footer" align="right">
<template #footer><div align="right">
<Button @click="modalVisible = false" style="margin-right: 10px">取消</Button>
<Button type="primary" @click="submitModal">提交</Button>
</div>
</div></template>
</Modal>
<!-- 专业新增编辑弹窗 -->
<Modal v-model="majorModalVisible" :title="majorModalTitle" width="460">
<Form ref="majorFormRef" :model="majorForm" :rules="majorFormRule" label-width="90">
<Form ref="majorFormRef" :model="majorForm" :rules="majorFormRule" :label-width="90">
<FormItem label="专业代码">
<Input v-model="majorForm.code" placeholder="请输入专业代码" />
</FormItem>
@@ -138,15 +134,16 @@
<Input v-model="majorForm.schsystemLeng" type="number" placeholder="请输入学制" />
</FormItem>
</Form>
<div slot="footer" align="right">
<template #footer><div align="right">
<Button @click="majorModalVisible = false" style="margin-right: 10px">取消</Button>
<Button type="primary" @click="submitMajorModal">提交</Button>
</div>
</div></template>
</Modal>
</div>
</template>
<script>
import { Button, Icon } from "view-ui-plus";
import draggable from 'vuedraggable'
import Sortable from 'sortablejs'
export default {
@@ -190,19 +187,13 @@ export default {
width: 170,
render: (h, params) => {
return h('div', { style: 'display:flex;gap:8px;justify-content:center;align-items:center' }, [
h('Button', {
props: { type: 'text', icon: 'ios-create', size: 'small' },
on: { click: () => this.openMajorEdit(params.index) }
}),
h('Button', {
props: { type: 'text', icon: 'ios-trash', size: 'small' },
on: { click: () => this.delMajor(params.index) }
}),
h(Button, {type: 'text', icon: 'ios-create', size: 'small',
onClick: () => this.openMajorEdit(params.index)}),
h(Button, {type: 'text', icon: 'ios-trash', size: 'small',
onClick: () => this.delMajor(params.index)}),
// 拖拽把手class固定为 drag-handle
h('Icon', {
props: { type: 'ios-move', size: 18, title: '拖动排序' },
class: 'drag-handle drag-icon'
})
h(Icon, {type: 'ios-move', size: 18, title: '拖动排序',
class: 'drag-handle drag-icon'})
])
}
}
@@ -246,7 +237,7 @@ export default {
}
}, 120)
},
beforeDestroy() {
beforeUnmount() {
if (this.tableDrag) this.tableDrag.destroy()
},
methods: {