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

208 lines
8.5 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.
/* 顾问管理:增删改查 + 服务端筛选与分页
名下还挂着学生的顾问不允许删除,后端会拦下来并返回中文提示 */
window.PAGES.push({
key: 'advisors',
title: '顾问管理',
sub: '招生顾问及其负责区域,名下还有学生时不可删除',
group: '数据管理',
icon: 'advisor',
component: {
name: 'AdvisorsPage',
template: `
<div>
<div class="card">
<div class="filters">
<el-input v-model="filter.adv_name" placeholder="姓名(模糊)" clearable style="width:150px" @keyup.enter="load" />
<el-input v-model="filter.adv_phone" placeholder="手机号(模糊)" clearable style="width:160px" @keyup.enter="load" />
<el-input v-model="filter.adv_region" placeholder="区域(模糊)" clearable style="width:150px" @keyup.enter="load" />
<el-select v-model="filter.adv_gender" placeholder="全部性别" clearable style="width:130px">
<el-option v-for="g in GENDER_OPTIONS" :key="g" :label="g" :value="g" />
</el-select>
<el-button type="primary" @click="load">查询</el-button>
<el-button @click="reset">重置</el-button>
</div>
<div class="card-head">
<div>
<div class="card-title">顾问列表</div>
<div class="card-hint">共 {{ total }} 位顾问</div>
</div>
<div class="card-tools">
<el-button type="primary" @click="openCreate">+ 新增顾问</el-button>
</div>
</div>
<el-table :data="rows" v-loading="loading" border stripe row-key="adv_id">
<el-table-column prop="adv_id" label="编号" width="80" />
<el-table-column prop="adv_name" label="姓名" width="120" />
<el-table-column label="性别" width="80">
<template #default="{ row }">
<el-tag v-if="row.adv_gender" size="small"
:type="row.adv_gender === '男' ? 'primary' : 'danger'" effect="light">
{{ row.adv_gender }}
</el-tag>
<span v-else class="muted">—</span>
</template>
</el-table-column>
<el-table-column prop="adv_phone" label="手机号" width="150">
<template #default="{ row }">{{ dash(row.adv_phone) }}</template>
</el-table-column>
<el-table-column prop="adv_email" label="邮箱" min-width="160" show-overflow-tooltip>
<template #default="{ row }">{{ dash(row.adv_email) }}</template>
</el-table-column>
<el-table-column prop="adv_region" label="负责区域" width="160" show-overflow-tooltip>
<template #default="{ row }">{{ dash(row.adv_region) }}</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>
<div class="pager">
<el-pagination background layout="total, sizes, prev, pager, next"
:total="total" v-model:current-page="skipPage"
v-model:page-size="limit" :page-sizes="[10, 20, 50, 100]" />
</div>
</div>
<el-dialog v-model="dialog" :title="editing ? '编辑顾问' : '新增顾问'" width="620px" destroy-on-close>
<el-form ref="formRef" :model="form" :rules="rules" label-width="88px">
<div class="form-grid">
<el-form-item label="姓名" prop="adv_name">
<el-input v-model="form.adv_name" placeholder="顾问姓名" maxlength="50" />
</el-form-item>
<el-form-item label="性别">
<el-select v-model="form.adv_gender" placeholder="可不选" clearable style="width:100%">
<el-option v-for="g in GENDER_OPTIONS" :key="g" :label="g" :value="g" />
</el-select>
</el-form-item>
<el-form-item label="手机号">
<el-input v-model="form.adv_phone" placeholder="手机号" maxlength="20" />
</el-form-item>
<el-form-item label="邮箱">
<el-input v-model="form.adv_email" placeholder="邮箱" maxlength="64" />
</el-form-item>
<el-form-item label="负责区域" class="span2">
<el-input v-model="form.adv_region" placeholder="如 广东 深圳 / 校招渠道" maxlength="64" />
</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 total = ref(0);
const dialog = ref(false);
const editing = ref(null);
const formRef = ref(null);
// 接口用 skip/limit 分页,skip 由页码换算
const limit = ref(10);
const skipPage = ref(1);
const filter = ref({ adv_name: '', adv_phone: '', adv_region: '', adv_gender: null });
const emptyForm = () => ({ adv_name: '', adv_gender: null, adv_phone: '', adv_email: '', adv_region: '' });
const form = ref(emptyForm());
const rules = {
adv_name: [{ required: true, message: '请填写姓名', trigger: 'blur' }],
};
const load = async () => {
loading.value = true;
try {
// 先按当前条件取一批,用来判断总数:接口不返回总数,
// 所以拿 limit=1000 的一次全量结果算,再切当前页显示。
const all = await AdvisorApi.list({
adv_name: filter.value.adv_name,
adv_phone: filter.value.adv_phone,
adv_region: filter.value.adv_region,
adv_gender: filter.value.adv_gender,
limit: 1000,
});
total.value = all.length;
const start = (skipPage.value - 1) * limit.value;
rows.value = all.slice(start, start + limit.value);
} catch (e) { toastErr(e); }
finally { loading.value = false; }
};
const reset = () => {
filter.value = { adv_name: '', adv_phone: '', adv_region: '', adv_gender: null };
skipPage.value = 1;
load();
};
const openCreate = () => {
editing.value = null;
form.value = emptyForm();
dialog.value = true;
};
const openEdit = (row) => {
editing.value = row.adv_id;
form.value = {
adv_name: row.adv_name, adv_gender: row.adv_gender, adv_phone: row.adv_phone,
adv_email: row.adv_email, adv_region: row.adv_region,
};
dialog.value = true;
};
const submit = async () => {
if (!formRef.value) return;
try { await formRef.value.validate(); } catch (e) { return; }
saving.value = true;
try {
if (editing.value) {
await AdvisorApi.update(editing.value, pruneEmpty(form.value));
toastOk('修改成功');
} else {
await AdvisorApi.create(pruneEmpty(form.value));
toastOk('新增成功');
}
Cache.invalidate('advisors');
dialog.value = false;
await load();
} catch (e) { toastErr(e); }
finally { saving.value = false; }
};
const remove = async (row) => {
try {
await ElementPlus.ElMessageBox.confirm(
`确定删除顾问「${row.adv_name}」吗?`,
'删除确认', { type: 'warning', confirmButtonText: '确定删除', cancelButtonText: '取消' });
} catch (e) { return; }
try {
await AdvisorApi.remove(row.adv_id);
toastOk('删除成功');
Cache.invalidate('advisors');
await load();
} catch (e) { toastErr(e); }
};
// 翻页 / 改每页条数都要重新取
watch([skipPage, limit], load);
onMounted(load);
return { loading, saving, rows, total, limit, skipPage, filter, dialog, editing,
formRef, form, rules, load, reset, openCreate, openEdit, submit, remove,
GENDER_OPTIONS, dash };
},
},
});