Compare commits
7 Commits
5e0207b224
...
beda8b5de7
| Author | SHA1 | Date | |
|---|---|---|---|
| beda8b5de7 | |||
| 994cf0c892 | |||
| c6788d210b | |||
| 73f9741a88 | |||
| 9f39a822f7 | |||
| 2fb5ffadc8 | |||
| 08571869b5 |
@@ -5,3 +5,9 @@
|
||||
vConsole 仅在当前用户有 `SYS_CAN_SUDO` tag 时显示。判断逻辑在 `src/App.vue:updateVConsoleVisibility()`。
|
||||
|
||||
Tags 通过 `get_all_tags_of_the_user` API 异步加载(`src/store/user.ts:getTags()`),在 `setCurrentUser()` 之后执行。vConsole 的 watch 需要 `{ deep: true }` 以及独立的 `store.current.tags` watch 来覆盖异步加载完成后的触发。
|
||||
|
||||
## 版本号 debug 日志
|
||||
|
||||
`src/App.vue:onMounted()` 中有一条 `console.debug('[App.vue] deploy_ver=YYYYMMDD.NNN')`(如 `20260503.001`)。
|
||||
|
||||
**每次部署前必须递增这个版本号**:当天第一次部署用 `.001`,第二次用 `.002`,依此类推。跨天重置为 `.001`。这样在 vConsole 中就能精确确认小程序加载的是哪一次部署的 JS。
|
||||
|
||||
@@ -70,6 +70,7 @@ export default defineComponent({
|
||||
const badge_props: Partial<BadgeProps> = { showZero: false, max: 99 }
|
||||
|
||||
onMounted(() => {
|
||||
console.debug('[App.vue] deploy_ver=20260503.003');
|
||||
let vconsole = document.getElementById("__vconsole");
|
||||
if (vconsole) {
|
||||
vconsole.hidden = true;
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div v-if="hasMultipleDepts" class="current-dept">
|
||||
<span>当前部门:{{ currentDeptName || '未选择' }}</span>
|
||||
<van-button size="mini" plain type="primary" @click="showPicker = true">切换部门</van-button>
|
||||
<van-action-sheet
|
||||
v-model:show="showPicker"
|
||||
:actions="deptActions"
|
||||
@select="onSelect"
|
||||
cancel-text="取消"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, computed } from 'vue';
|
||||
import { ActionSheet, Button } from 'vant';
|
||||
import useOrg from '~/store/org';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'dept-switcher',
|
||||
components: {
|
||||
[ActionSheet.name!]: ActionSheet,
|
||||
[Button.name!]: Button,
|
||||
},
|
||||
setup() {
|
||||
const { store, switchDepartment } = useOrg();
|
||||
const showPicker = ref(false);
|
||||
|
||||
const hasMultipleDepts = computed(() => store.departments.length > 1);
|
||||
|
||||
const currentDeptName = computed(() => {
|
||||
if (!store.currentDepartmentId) return '';
|
||||
const dept = store.departments.find((d) => d.id === store.currentDepartmentId);
|
||||
return dept?.dept_name || '';
|
||||
});
|
||||
|
||||
const deptActions = computed(() =>
|
||||
store.departments.map((d) => ({
|
||||
name: d.dept_name,
|
||||
id: d.id,
|
||||
}))
|
||||
);
|
||||
|
||||
const onSelect = async (action: { name: string; id: string }) => {
|
||||
showPicker.value = false;
|
||||
if (action.id !== store.currentDepartmentId) {
|
||||
await switchDepartment(action.id);
|
||||
window.location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
return { hasMultipleDepts, currentDeptName, showPicker, deptActions, onSelect };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.current-dept {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 0.12rem;
|
||||
color: #666;
|
||||
margin-bottom: 0.12rem;
|
||||
}
|
||||
</style>
|
||||
@@ -20,6 +20,7 @@
|
||||
<span>当前机构:{{ currentOrgName || '未选择机构' }}</span>
|
||||
<van-button size="mini" plain type="primary" @click="goOrgSelect">切换机构</van-button>
|
||||
</div>
|
||||
<dept-switcher />
|
||||
<div v-if="isStudent" class="current-teacher">
|
||||
<span>当前老师:{{ currentTeacherName || '未选择老师' }}</span>
|
||||
<van-button size="mini" plain type="primary" @click="goTeacherSelect">切换老师</van-button>
|
||||
@@ -45,6 +46,7 @@ import { useRouter } from "vue-router";
|
||||
import {UpyunAccess} from "~/utils/upyun";
|
||||
import {CurrentUserRole, HtyAuthToken, HtySudoToken} from "~/utils";
|
||||
import useOrg from "~/store/org";
|
||||
import DeptSwitcher from "~/components/dept-switcher.vue";
|
||||
import useTeacher from "~/store/teacher";
|
||||
|
||||
export default defineComponent({
|
||||
@@ -54,13 +56,14 @@ export default defineComponent({
|
||||
[Icon.name!]: Icon,
|
||||
[Tag.name!]: Tag,
|
||||
[ActionSheet.name!]: ActionSheet,
|
||||
[Button.name!]: Button
|
||||
[Button.name!]: Button,
|
||||
DeptSwitcher,
|
||||
},
|
||||
setup() {
|
||||
const switching = ref(false);
|
||||
const router = useRouter();
|
||||
const { store, chooseRole, update, logout } = useUser(router);
|
||||
const { store: orgStore, loadMyOrgs } = useOrg();
|
||||
const { store: orgStore, loadMyOrgs, loadMyDepartments } = useOrg();
|
||||
const { store: teacherStore, switchTeacher } = useTeacher();
|
||||
const user = computed(() => store.current)
|
||||
const state = reactive({
|
||||
@@ -167,6 +170,9 @@ export default defineComponent({
|
||||
if (!orgStore.orgs.length) {
|
||||
await loadMyOrgs();
|
||||
}
|
||||
if (!orgStore.departments.length) {
|
||||
await loadMyDepartments();
|
||||
}
|
||||
});
|
||||
|
||||
return { switching, hasMultiRoles, roles, user, currentRole, switchRole, editAvatar, avatarUrl, editName, state, logoutUser, currentOrgName, goOrgSelect, isStudent, currentTeacherName, goTeacherSelect }
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<van-search shape="round" v-model.trim="state.keyword" />
|
||||
</div>
|
||||
<div class="list">
|
||||
<van-pull-refresh v-model="state.loading" @refresh="onRefresh">
|
||||
<van-pull-refresh v-model="state.refreshing" @refresh="onRefresh">
|
||||
<van-list v-model:loading="state.loading"
|
||||
:finished="state.finished" finished-text="没有更多数据了"
|
||||
@load="onPage">
|
||||
@@ -102,7 +102,9 @@ export default defineComponent({
|
||||
|
||||
const state = reactive({
|
||||
keyword: '',
|
||||
loading: false, finished: true,
|
||||
refreshing: false,
|
||||
loading: false,
|
||||
finished: true,
|
||||
start_date: '',
|
||||
page: 1,
|
||||
page_size: 10,
|
||||
@@ -123,14 +125,19 @@ export default defineComponent({
|
||||
if (start_date) {
|
||||
params.start_date = start_date + " 00:00:00";
|
||||
}
|
||||
await query(params);
|
||||
if (store.pages <= state.page) {
|
||||
state.finished = true;
|
||||
try {
|
||||
await query(params);
|
||||
if (store.pages <= state.page) {
|
||||
state.finished = true;
|
||||
}
|
||||
} finally {
|
||||
state.loading = false;
|
||||
state.refreshing = false;
|
||||
}
|
||||
state.loading = false;
|
||||
}
|
||||
|
||||
const onRefresh = async () => {
|
||||
state.refreshing = true;
|
||||
await search({page: 1, page_size: state.page_size});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user