dev #5

Merged
hy merged 3 commits from dev into staging 2025-08-26 10:23:47 +08:00
5 changed files with 108 additions and 99 deletions
Showing only changes of commit d90c357cad - Show all commits

View File

@ -10,13 +10,20 @@ import {
onUnmounted, onUnmounted,
getCurrentInstance, getCurrentInstance,
onBeforeMount, onBeforeMount,
PropType PropType,
shallowRef,
} from "vue"; } from "vue";
import { Search } from "@element-plus/icons-vue"; import { Search } from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus"; import { ElMessage, ElMessageBox } from "element-plus";
import { defineAsyncComponent, AsyncComponentLoader } from "vue"; import { defineAsyncComponent, AsyncComponentLoader } from "vue";
import { ConditionalType, Dialog, TableColumn, TableConfig } from "./hTable"; import {
ButtonCustomConfig,
ConditionalType,
Dialog,
TableColumn,
TableConfig,
} from "./hTable";
import hTableEdit from "./hTableEdit.vue"; import hTableEdit from "./hTableEdit.vue";
import { hTableAPI } from "@/api/hTable"; import { hTableAPI } from "@/api/hTable";
import { getenum } from "@/api/enum"; import { getenum } from "@/api/enum";
@ -27,12 +34,12 @@ const props = defineProps({
//** */ //** */
Row: { Row: {
type: Object as PropType<any>, type: Object as PropType<any>,
default: () => ({}) default: () => ({}),
}, },
tableConfig: { tableConfig: {
type: Object as PropType<TableConfig>, type: Object as PropType<TableConfig>,
default: () => ({}) default: () => ({}),
} },
}); });
const table = ref<TableConfig>(props.tableConfig); const table = ref<TableConfig>(props.tableConfig);
@ -78,13 +85,13 @@ const dialog = ref<Dialog>({
data: [], data: [],
custom: {}, custom: {},
component: null, // component: null, //
visible: false // visible: false, //
}, },
edit: { edit: {
id: -1, id: -1,
title: "", // title title: "", // title
visible: false // visible: false, //
} },
}); });
const appB = ref<HTMLElement>(null); const appB = ref<HTMLElement>(null);
@ -112,8 +119,7 @@ function intdata() {
if (element.add === undefined) element.add = false; if (element.add === undefined) element.add = false;
if (element.edit === undefined) element.edit = false; if (element.edit === undefined) element.edit = false;
// Vue 3 $set // Vue 3 $set
if (element.valueE === undefined) if (element.valueE === undefined) element.valueE = element.multiple ? [] : "";
element.valueE = element.multiple ? [] : "";
if (element.value === undefined) element.value = element.multiple ? [] : ""; if (element.value === undefined) element.value = element.multiple ? [] : "";
if (!element.type) element.type = "string"; if (!element.type) element.type = "string";
if (element.show === undefined) element.show = true; if (element.show === undefined) element.show = true;
@ -137,21 +143,21 @@ function rowKeyFun(row) {
return row.customId; return row.customId;
} }
function execute(obj, scope, btn) { function execute(obj, scope, btn) {
if (Object.prototype.toString.call(obj) === "[object Function]") if (Object.prototype.toString.call(obj) === "[object Function]") return obj(scope, btn);
return obj(scope, btn);
return eval(obj); return eval(obj);
} }
function getOperationColumnWidth() { function getOperationColumnWidth() {
let hFontSize = getComputedStyle(window.document.documentElement)[ let hFontSize = getComputedStyle(window.document.documentElement)["font-size"].replace(
"font-size" "px",
].replace("px", ""); ""
);
let defWidth = 10 + 2 + 30; let defWidth = 10 + 2 + 30;
let width = eval( let width = eval(
table.value.operationColumnData table.value.operationColumnData
.filter(s => !s.topBtn && s.show) .filter((s) => !s.topBtn && s.show)
.map(s => defWidth + s.label.length * (hFontSize || 16)) .map((s) => defWidth + s.label.length * (hFontSize || 16))
.join("+") .join("+")
); );
width = width < 100 ? 100 : width; width = width < 100 ? 100 : width;
@ -190,13 +196,18 @@ function handleEdit(obj, row) {
dialog.value.visible = true; dialog.value.visible = true;
dialog.value.width = "500px"; dialog.value.width = "500px";
} }
function handleCustom(obj, row, custom) { async function handleCustom(obj, row, custom: ButtonCustomConfig) {
dialog.value.custom.data = row || []; dialog.value.custom.data = row || [];
dialog.value.custom.custom = custom || []; dialog.value.custom.custom = custom || [];
// //
dialog.value.custom.component = defineAsyncComponent({ dialog.value.custom.component = defineAsyncComponent({
loader: () => import(/* @vite-ignore */ `../../views/${custom.src}.vue`) loader: () => import(/* @vite-ignore */ `../../views/${custom.src}.vue`),
}); });
// let r = shallowRef(null);
// const module = await import(custom.src);
// r.value = module.default;
// dialog.value.custom.component = r;
dialog.value.width = custom.width; dialog.value.width = custom.width;
dialog.value.title = custom.title; dialog.value.title = custom.title;
dialog.value.edit.visible = false; dialog.value.edit.visible = false;
@ -215,11 +226,11 @@ function handleDelete(obj, row) {
return; return;
} }
const ids: any[] = []; const ids: any[] = [];
row.forEach(it => { row.forEach((it) => {
ids.push(it.id); ids.push(it.id);
}); });
ElMessageBox.confirm("此操作将永久删除勾选记录, 是否继续?").then(() => { ElMessageBox.confirm("此操作将永久删除勾选记录, 是否继续?").then(() => {
Api.delete(ids).then(res => { Api.delete(ids).then((res) => {
if (res.code === 200) { if (res.code === 200) {
handleReloadPaged(); handleReloadPaged();
ElMessage.success("删除成功"); ElMessage.success("删除成功");
@ -256,10 +267,7 @@ function handleSelectionChange(selection) {
} }
// //
function handleReloadPaged(reload = true) { function handleReloadPaged(reload = true) {
if ( if (table.value.search === undefined || table.value.search.PageIndex === undefined) {
table.value.search === undefined ||
table.value.search.PageIndex === undefined
) {
table.value.search.PageIndex = 0; table.value.search.PageIndex = 0;
table.value.search.PageSize = 20; table.value.search.PageSize = 20;
} }
@ -321,17 +329,17 @@ async function fetchInitData() {
element.type === undefined) element.type === undefined)
) { ) {
if (element.type === "string" || element.type === undefined) if (element.type === "string" || element.type === undefined)
element.custom = row => row[key]; element.custom = (row) => row[key];
else { else {
element.custom = row => { element.custom = (row) => {
let sc = element.setting.datasource.find( let sc = element.setting.datasource.find(
s => s[element.setting.mapValue] + "" == row[key] + "" (s) => s[element.setting.mapValue] + "" == row[key] + ""
); );
return !sc ? row[key] : sc[element.setting.maplabel]; return !sc ? row[key] : sc[element.setting.maplabel];
}; };
} }
} else if (element.custom == undefined) { } else if (element.custom == undefined) {
element.custom = row => row[key]; element.custom = (row) => row[key];
} }
} }
setTimeout(() => { setTimeout(() => {
@ -343,9 +351,7 @@ function showTips(item, value) {
if (item.width == undefined) { if (item.width == undefined) {
return false; return false;
} }
return ( return getByteLen(item.custom(value) + "") * 16 < item.width.replace("px", "");
getByteLen(item.custom(value) + "") * 16 < item.width.replace("px", "")
);
} }
function getByteLen(str) { function getByteLen(str) {
let len = 0; let len = 0;
@ -358,11 +364,11 @@ function getByteLen(str) {
function fetchPagedData() { function fetchPagedData() {
for (const iterator of table.value.search.defaultConditions) { for (const iterator of table.value.search.defaultConditions) {
if (!iterator) continue; if (!iterator) continue;
if (!table.value.search.Conditions.find(s => s == iterator)) { if (!table.value.search.Conditions.find((s) => s == iterator)) {
table.value.search.Conditions.push(iterator); table.value.search.Conditions.push(iterator);
} }
} }
Api.PageList(table.value.search).then(res => { Api.PageList(table.value.search).then((res) => {
if (res.code === 200) { if (res.code === 200) {
table.value.data = res.data.data.map((s, i) => { table.value.data = res.data.data.map((s, i) => {
return { ...s, customId: i }; return { ...s, customId: i };
@ -378,11 +384,7 @@ function fetchPagedData() {
<div ref="appB_S" class="search-container1"> <div ref="appB_S" class="search-container1">
<!-- 搜索项目 --> <!-- 搜索项目 -->
<el-form v-if="table.search.show" :inline="true" :model="table.search"> <el-form v-if="table.search.show" :inline="true" :model="table.search">
<el-form-item <el-form-item v-for="(o, n, i) in table.column" v-show="o.search" :key="i">
v-for="(o, n, i) in table.column"
v-show="o.search"
:key="i"
>
<el-date-picker <el-date-picker
v-if="o.type.trim() == 'datetime'" v-if="o.type.trim() == 'datetime'"
v-model="o.value as Date" v-model="o.value as Date"
@ -424,10 +426,7 @@ function fetchPagedData() {
<el-input v-else v-model="o.value as string" :placeholder="o.label" /> <el-input v-else v-model="o.value as string" :placeholder="o.label" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button <el-button type="primary" :icon="Search" @click="handleReloadPaged(false)"
type="primary"
:icon="Search"
@click="handleReloadPaged(false)"
>查询</el-button >查询</el-button
> >
</el-form-item> </el-form-item>
@ -471,7 +470,7 @@ function fetchPagedData() {
<!-- 头部按钮组 --> <!-- 头部按钮组 -->
<el-button <el-button
v-for="(e, i) in table.operationColumnData.filter( v-for="(e, i) in table.operationColumnData.filter(
s => s.topBtn && hasPerms(s.perms) (s) => s.topBtn && hasPerms(s.perms)
)" )"
v-show="execute(e['show'], {}, e)" v-show="execute(e['show'], {}, e)"
:key="i" :key="i"
@ -495,7 +494,7 @@ function fetchPagedData() {
<el-table-column <el-table-column
v-if=" v-if="
table.operationColumn && table.operationColumn &&
table.operationColumnData.filter(s => !s.topBtn).length > 0 table.operationColumnData.filter((s) => !s.topBtn).length > 0
" "
label="操作" label="操作"
:width="getOperationColumnWidth()" :width="getOperationColumnWidth()"
@ -504,7 +503,7 @@ function fetchPagedData() {
<div class="columnTemplate"> <div class="columnTemplate">
<el-button <el-button
v-for="(e, i) in table.operationColumnData.filter( v-for="(e, i) in table.operationColumnData.filter(
s => !s.topBtn && hasPerms(s.perms) (s) => !s.topBtn && hasPerms(s.perms)
)" )"
v-show="execute(e['show'], scope, e)" v-show="execute(e['show'], scope, e)"
:key="i" :key="i"

View File

@ -9,7 +9,7 @@ import { ruleRequired, ruleRequiredNumber } from "@/utils/rules";
const ControllerName = "ExamUserInfo"; const ControllerName = "ExamUserInfo";
defineOptions({ defineOptions({
name: ControllerName name: ControllerName,
}); });
const props = defineProps<{ const props = defineProps<{
@ -30,8 +30,13 @@ const tableData: TableConfig = {
PageSize: 60, PageSize: 60,
OrderBy: "AssignRanking", // OrderBy: "AssignRanking", //
OrderByType: 0, OrderByType: 0,
defaultConditions: [], // defaultConditions: [
Conditions: [] {
FieldName: "ExamId",
FieldValue: props.data[0].examId + "",
},
], //
Conditions: [],
}, },
operationColumn: true, // operationColumn: true, //
operationColumnData: [ operationColumnData: [
@ -43,7 +48,7 @@ const tableData: TableConfig = {
click: (o, r, c) => { click: (o, r, c) => {
tableData.search.OrderByType = 1; tableData.search.OrderByType = 1;
c(); c();
} },
}, },
{ {
// //
@ -53,7 +58,7 @@ const tableData: TableConfig = {
click: (o, r, c) => { click: (o, r, c) => {
tableData.search.OrderByType = 0; tableData.search.OrderByType = 0;
c(); c();
} },
}, },
{ {
topBtn: false, // topBtn: false, //
@ -64,9 +69,9 @@ const tableData: TableConfig = {
title: "考试学生班级详情", // title title: "考试学生班级详情", // title
src: "exam/userExam", // src: "exam/userExam", //
width: "1600px", // width: "1600px", //
height: "800px" // height: "800px", //
} },
} },
], ],
column: { column: {
// //
@ -74,78 +79,78 @@ const tableData: TableConfig = {
label: "姓名", label: "姓名",
search: true, search: true,
searchType: ConditionalType.Like, // searchType: ConditionalType.Like, //
width: "180px" width: "180px",
}, },
语文: { 语文: {
label: "语文", label: "语文",
search: false, search: false,
width: "100px", width: "100px",
custom: row => row.subjectDic.语文 custom: (row) => row.subjectDic.语文,
}, },
数学: { 数学: {
label: "数学", label: "数学",
search: false, search: false,
width: "100px", width: "100px",
custom: row => row.subjectDic.数学 custom: (row) => row.subjectDic.数学,
}, },
英语: { 英语: {
label: "英语", label: "英语",
search: false, search: false,
width: "100px", width: "100px",
custom: row => row.subjectDic.英语 custom: (row) => row.subjectDic.英语,
}, },
物理: { 物理: {
label: "物理", label: "物理",
search: false, search: false,
width: "100px", width: "100px",
custom: row => row.subjectDic.物理 custom: (row) => row.subjectDic.物理,
}, },
化学: { 化学: {
label: "化学", label: "化学",
search: false, search: false,
width: "100px", width: "100px",
custom: row => row.subjectDic.化学 custom: (row) => row.subjectDic.化学,
}, },
生物: { 生物: {
label: "生物", label: "生物",
search: false, search: false,
width: "100px", width: "100px",
custom: row => row.subjectDic.生物 custom: (row) => row.subjectDic.生物,
}, },
政治: { 政治: {
label: "政治", label: "政治",
search: false, search: false,
width: "100px", width: "100px",
custom: row => row.subjectDic.政治 custom: (row) => row.subjectDic.政治,
}, },
历史: { 历史: {
label: "历史", label: "历史",
search: false, search: false,
width: "100px", width: "100px",
custom: row => row.subjectDic.历史 custom: (row) => row.subjectDic.历史,
}, },
地理: { 地理: {
label: "地理", label: "地理",
search: false, search: false,
width: "100px", width: "100px",
custom: row => row.subjectDic.地理 ?? "--" custom: (row) => row.subjectDic.地理 ?? "--",
}, },
assignScore: { assignScore: {
label: "赋分总分", label: "赋分总分",
search: false, search: false,
width: "180px" width: "180px",
}, },
assignRanking: { assignRanking: {
label: "赋分后的排名", label: "赋分后的排名",
search: false, search: false,
width: "200px" width: "200px",
} },
}, },
data: [], data: [],
pageData: { pageData: {
total: 0 total: 0,
}, },
selectRows: [] selectRows: [],
}; };
const showTable = ref(false); const showTable = ref(false);
@ -160,10 +165,10 @@ const exam = props.data[0];
<template> <template>
<div> <div>
<div class="p-[10px] text-[1.5rem]"> <div class="p-[10px] text-[1.5rem]">
<strong>学校</strong>{{ exam.schoolName }}&nbsp;&nbsp; <strong>学校</strong>{{ exam.schoolName }}&nbsp;&nbsp; <strong>年级</strong
<strong>年级</strong>{{ exam.gradeLevel + exam.gradeYear }}&nbsp;&nbsp; >{{ exam.gradeLevel + exam.gradeYear }}&nbsp;&nbsp; <strong>班级</strong
<strong>班级</strong>{{ exam.className }}&nbsp;&nbsp; >{{ exam.className }}&nbsp;&nbsp; <strong>考试名称</strong
<strong>考试名称</strong>{{ exam.examName }}&nbsp;&nbsp; >{{ exam.examName }}&nbsp;&nbsp;
<!-- <strong>考试类型</strong>{{exam.className}}&nbsp;&nbsp; <!-- <strong>考试类型</strong>{{exam.className}}&nbsp;&nbsp;
<strong>试卷类型</strong>{{exam.className}}&nbsp;&nbsp; --> <strong>试卷类型</strong>{{exam.className}}&nbsp;&nbsp; -->
</div> </div>

View File

@ -77,7 +77,7 @@
style="width: 180px" style="width: 180px"
> >
<el-option <el-option
v-for="(item, i) in reliefSubTimeEnum" v-for="(item, i) in reliefTypeEnum"
:key="i" :key="i"
autocomplete="off" autocomplete="off"
:label="item.text" :label="item.text"
@ -105,12 +105,14 @@
<el-select <el-select
v-model="form.gLSubject" v-model="form.gLSubject"
filterable filterable
clearable
placeholder="历史/地理" placeholder="历史/地理"
style="width: 180px" style="width: 180px"
> >
<el-option <el-option
v-for="(item, i) in subject1" v-for="(item, i) in subject1"
:key="i" :key="i"
clearable
autocomplete="off" autocomplete="off"
:label="item.text" :label="item.text"
:value="item.value" :value="item.value"
@ -121,6 +123,7 @@
<el-select <el-select
v-model="form.gSubject1" v-model="form.gSubject1"
filterable filterable
clearable
placeholder="小学科" placeholder="小学科"
style="width: 180px" style="width: 180px"
> >
@ -161,8 +164,8 @@
</el-row> </el-row>
<el-row class="pt-4"> <el-row class="pt-4">
<el-col :span="24"> <el-col :span="24">
<el-form-item label="职位" prop="positionIds" :rules="ruleRequired"> <el-form-item label="就读班级" prop="positionIds" :rules="ruleRequired">
<el-button type="success" @click="CheckPosition()">分配职位</el-button> <el-button type="success" @click="CheckPosition()">选择就读班级</el-button>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@ -283,7 +286,7 @@ const formLabelWidth = "120px";
const size = "small"; const size = "small";
const loading = ref(false); const loading = ref(false);
const reliefSubTimeEnum = ref<ComboModel[]>(); const reliefTypeEnum = ref<ComboModel[]>();
const subject1 = ref<ComboModel[]>([ const subject1 = ref<ComboModel[]>([
{ value: 4, text: "物理" }, { value: 4, text: "物理" },
@ -323,7 +326,7 @@ const defaultSubjectLevel = reactive({
const form = ref<FormData>({ const form = ref<FormData>({
id: props.id, id: props.id,
account: "", account: "",
userType: 2, userType: 1,
level: 0, level: 0,
passWord: "", passWord: "",
realName: "", realName: "",
@ -443,7 +446,22 @@ const handleResetForm = () => {
}; };
const fetchInitData = async () => { const fetchInitData = async () => {
reliefSubTimeEnum.value = (await getenum("ReliefSubTimeEnum")).data; reliefTypeEnum.value = `
1.复读生
2.艺术生
3.春招生
4.领导承诺批准全免
5.资源班
6.国际班
7.合同制收费学校
8.渠道商家属
9.新开班但领导承诺第一学期不收费`
.split("\n")
.filter((s) => s.trim())
.map((s) => {
const [value, text] = s.trim().split(".");
return { value: text.trim(), text: text.trim() };
});
}; };
const fetchFormData = async () => { const fetchFormData = async () => {
@ -494,7 +512,7 @@ const userTypeChange = () => {
}; };
const CheckPosition = () => { const CheckPosition = () => {
dialog.title = "选择职位"; dialog.title = "选择就读班级";
dialog.visible = true; dialog.visible = true;
PositionFormIds.value = positionList.value PositionFormIds.value = positionList.value
.filter((s) => s.enable !== false) .filter((s) => s.enable !== false)

View File

@ -84,28 +84,11 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item style="width: 100px">
<el-select v-model="search.subjectId" placeholder="科目" clearable filterable>
<el-option
v-for="item in subjectList"
:key="item.value"
:label="item.text"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="handleReloadPaged" :icon="Search" <el-button type="primary" @click="handleReloadPaged" :icon="Search"
>查询</el-button >查询</el-button
> >
</el-form-item> </el-form-item>
<el-form-item v-show="selectUser">
<el-button type="success" @click="selectUserCallBack()" icon="el-icon-check"
>选择用户</el-button
>
</el-form-item>
</el-form> </el-form>
</div> </div>
<div class="toolbar-container" v-show="!selectUser"> <div class="toolbar-container" v-show="!selectUser">

View File

@ -106,7 +106,9 @@
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="success" @click="asyncPosition">选择勾选职位</el-button> <el-button type="success" @click="asyncPosition">{{
userType == 1 ? "选择勾选班级" : "选择勾选职位"
}}</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
@ -163,7 +165,9 @@
<el-card class="box-card"> <el-card class="box-card">
<div class="clearfix clearfixCss"> <div class="clearfix clearfixCss">
<span style="line-height: 32px; font-weight: 600" <span style="line-height: 32px; font-weight: 600"
>已选职位[{{ selectPositions.length }}]</span >{{ userType == 1 ? "就读班级" : "已选职位" }}[{{
selectPositions.length
}}]</span
> >
<el-button <el-button
style="float: right" style="float: right"