206 lines
8.6 KiB
JavaScript
206 lines
8.6 KiB
JavaScript
/* 就业管理:增删改查
|
||
学号必须从学生下拉框里选:表的 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 };
|
||
},
|
||
},
|
||
});
|