Files
1/static/js/pages/emps.js
T
2026-09-14 10:23:36 +08:00

206 lines
8.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* 就业管理:增删改查
学号必须从学生下拉框里选:表的 stu_no 是指向 wl_student 的外键,
手填一个不存在的学号会直接撞外键约束报 500 */
window.PAGES.push({
key: 'emps',
title: '就业管理',
sub: '学生就业去向与薪资,一个学生一条记录',
group: '数据管理',
icon: 'emp',
component: {
name: 'EmpsPage',
template: `
<div>
<div class="card">
<div class="filters">
<el-input v-model="filter.company_name" placeholder="公司名称(模糊)" clearable style="width:200px" @keyup.enter="load" />
<el-input v-model="keyword" placeholder="按学号筛选" clearable style="width:160px" />
<el-button type="primary" @click="load">查询</el-button>
<el-button @click="reset">重置</el-button>
<span class="muted">共 {{ filtered.length }} 条</span>
</div>
<div class="card-head">
<div class="card-title">就业列表</div>
<div class="card-tools">
<el-button type="primary" @click="openCreate">+ 新增就业</el-button>
</div>
</div>
<el-table :data="filtered" v-loading="loading" border stripe row-key="stu_no">
<el-table-column prop="stu_no" label="学号" width="130" />
<el-table-column label="学生姓名" width="120">
<template #default="{ row }">
<span v-if="row.stu_name">{{ row.stu_name }}</span>
<el-tag v-else size="small" type="info" effect="plain">学生已删除</el-tag>
</template>
</el-table-column>
<el-table-column prop="company_name" label="公司名称" min-width="170" show-overflow-tooltip />
<el-table-column label="薪资" width="110">
<template #default="{ row }">
<span v-if="row.salary">{{ row.salary.toLocaleString() }}</span>
<span v-else class="muted">—</span>
</template>
</el-table-column>
<el-table-column label="就业开放时间" width="150">
<template #default="{ row }">{{ dash(fmtDateTime(row.emp_open_time)) }}</template>
</el-table-column>
<el-table-column label="offer 下发时间" width="150">
<template #default="{ row }">{{ dash(fmtDateTime(row.offer_time)) }}</template>
</el-table-column>
<el-table-column label="操作" width="140" fixed="right">
<template #default="{ row }">
<el-button link type="primary" @click="openEdit(row)">编辑</el-button>
<el-button link type="danger" @click="remove(row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-alert class="mt12" type="info" :closable="false" show-icon
title="薪资、两个时间留空时会走数据库默认值(薪资默认 15000,offer 时间取当前时间)" />
</div>
<el-dialog v-model="dialog" :title="editing ? '编辑就业信息' : '新增就业信息'" width="620px" destroy-on-close>
<el-form ref="formRef" :model="form" :rules="rules" label-width="104px">
<div class="form-grid">
<el-form-item label="学生" prop="stu_no" class="span2">
<el-select v-model="form.stu_no" placeholder="按学号或姓名搜索" filterable
:disabled="!!editing" style="width:100%">
<el-option v-for="s in students" :key="s.stu_no" :label="studentLabel(s)" :value="s.stu_no" />
</el-select>
</el-form-item>
<el-form-item label="公司名称" prop="company_name" class="span2">
<el-input v-model="form.company_name" placeholder="就业公司" maxlength="100" />
</el-form-item>
<el-form-item label="薪资">
<el-input-number v-model="form.salary" :min="0" :step="1000"
controls-position="right" style="width:100%" placeholder="默认 15000" />
</el-form-item>
<el-form-item label="就业开放时间">
<el-date-picker v-model="form.emp_open_time" type="datetime"
value-format="YYYY-MM-DDTHH:mm:ss" placeholder="可不填"
style="width:100%" />
</el-form-item>
<el-form-item label="offer 下发时间" class="span2">
<el-date-picker v-model="form.offer_time" type="datetime"
value-format="YYYY-MM-DDTHH:mm:ss" placeholder="可不填,默认当前时间"
style="width:100%" />
</el-form-item>
</div>
</el-form>
<template #footer>
<el-button @click="dialog = false">取消</el-button>
<el-button type="primary" :loading="saving" @click="submit">保存</el-button>
</template>
</el-dialog>
</div>
`,
setup() {
const loading = ref(false);
const saving = ref(false);
const rows = ref([]);
const students = ref([]);
const keyword = ref('');
const dialog = ref(false);
const editing = ref(null);
const formRef = ref(null);
const filter = ref({ company_name: '' });
const emptyForm = () => ({
stu_no: null, company_name: '', salary: null,
emp_open_time: null, offer_time: null,
});
const form = ref(emptyForm());
const rules = {
stu_no: [{ required: true, message: '请选择学生', trigger: 'change' }],
company_name: [{ required: true, message: '请填写公司名称', trigger: 'blur' }],
};
const filtered = computed(() => {
const k = keyword.value.trim().toLowerCase();
if (!k) return rows.value;
return rows.value.filter(r => String(r.stu_no || '').toLowerCase().includes(k));
});
const load = async () => {
loading.value = true;
try {
rows.value = await EmpApi.list({ company_name: filter.value.company_name, limit: 1000 });
} catch (e) { toastErr(e); }
finally { loading.value = false; }
};
const reset = () => {
filter.value = { company_name: '' };
keyword.value = '';
load();
};
const openCreate = () => {
editing.value = null;
form.value = emptyForm();
dialog.value = true;
};
const openEdit = (row) => {
// 学号是主键,EmpUpdate 里也没有这个字段,编辑时只允许改其余信息
editing.value = row.stu_no;
form.value = {
stu_no: row.stu_no, company_name: row.company_name, salary: row.salary,
emp_open_time: row.emp_open_time ? String(row.emp_open_time).slice(0, 19) : null,
offer_time: row.offer_time ? String(row.offer_time).slice(0, 19) : null,
};
dialog.value = true;
};
const submit = async () => {
if (!formRef.value) return;
try { await formRef.value.validate(); } catch (e) { return; }
saving.value = true;
try {
const payload = pruneEmpty(form.value);
if (editing.value) {
delete payload.stu_no; // 主键不参与修改
await EmpApi.update(editing.value, payload);
toastOk('保存成功');
} else {
await EmpApi.create(payload);
// 该学生的记录若曾被删除,后端会直接把旧记录复活,所以提示统一写"保存成功"
toastOk('保存成功');
}
dialog.value = false;
await load();
} catch (e) { toastErr(e); }
finally { saving.value = false; }
};
const remove = async (row) => {
try {
await ElementPlus.ElMessageBox.confirm(
`确定删除「${row.stu_name || row.stu_no}」的就业信息吗?`,
'删除确认', { type: 'warning', confirmButtonText: '确定删除', cancelButtonText: '取消' });
} catch (e) { return; }
try {
await EmpApi.remove(row.stu_no);
toastOk('删除成功');
await load();
} catch (e) { toastErr(e); }
};
onMounted(async () => {
try { students.value = await Cache.loadStudents(); }
catch (e) { toastErr(e); }
load();
});
return { loading, saving, rows, students, keyword, filtered, filter, dialog, editing,
formRef, form, rules, load, reset, openCreate, openEdit, submit, remove,
dash, fmtDateTime, studentLabel };
},
},
});