alumni-info.vue 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473
  1. <template>
  2. <div class="content-box">
  3. <div class="left">
  4. <!-- <el-icon :size="23" class="camera"><VideoCameraFilled /></el-icon> -->
  5. <span class="cameratxt">校友信息管理</span>
  6. </div>
  7. <div class="scroll">
  8. <div class="middle">
  9. <div class="filter">
  10. <div class="condition">
  11. <span>姓名 :</span>
  12. <el-input
  13. clearable
  14. v-model.trim="searchInput.name"
  15. class="w-50 m-2"
  16. placeholder="请输入姓名"
  17. style="width: 180px"
  18. />
  19. </div>
  20. <div class="condition">
  21. <span>院系 :</span>
  22. <el-select
  23. clearable
  24. v-model="searchInput.collegeId"
  25. placeholder="请选择院系"
  26. @change="collegeChange"
  27. >
  28. <el-option
  29. v-for="i in collegeData"
  30. :key="i.id"
  31. :label="i.name"
  32. :value="i.id"
  33. />
  34. </el-select>
  35. </div>
  36. <div class="condition">
  37. <span>入学年 :</span>
  38. <el-select
  39. clearable
  40. v-model="searchInput.periodId"
  41. placeholder="请选择入学年"
  42. @change="periodChange"
  43. >
  44. <el-option
  45. v-for="i in periodData"
  46. :key="i.id"
  47. :label="i.name"
  48. :value="i.id"
  49. />
  50. </el-select>
  51. </div>
  52. <div class="condition">
  53. <span>专业 :</span>
  54. <el-select
  55. clearable
  56. v-model="searchInput.majorId"
  57. placeholder="请选择专业"
  58. @change="majorChange"
  59. >
  60. <el-option
  61. v-for="i in majorData"
  62. :key="i.id"
  63. :label="i.name"
  64. :value="i.id"
  65. />
  66. </el-select>
  67. </div>
  68. <div class="condition">
  69. <span>班级 :</span>
  70. <el-select
  71. clearable
  72. v-model="searchInput.classId"
  73. placeholder="请选择班级"
  74. >
  75. <el-option
  76. v-for="i in classData"
  77. :key="i.id"
  78. :label="i.name"
  79. :value="i.id"
  80. />
  81. </el-select>
  82. </div>
  83. <div class="condition">
  84. <span>身份认证 :</span>
  85. <el-select
  86. clearable
  87. v-model="searchInput.identityType"
  88. placeholder="请选择身份认证"
  89. >
  90. <el-option
  91. v-for="i in identityData"
  92. :key="i.id"
  93. :label="i.name"
  94. :value="i.id"
  95. />
  96. </el-select>
  97. </div>
  98. <el-button
  99. style="margin-left: 20px"
  100. color="rgba(38, 151, 255, 1)"
  101. type="primary"
  102. class="search"
  103. @click="searchBtn"
  104. ><span>查询</span></el-button
  105. >
  106. <el-button @click="resetBtn" plain color="rgba(43, 153, 255, 1)"
  107. >重置</el-button
  108. >
  109. </div>
  110. <!-- 按钮列表 -->
  111. <div class="gongneng">
  112. <el-button
  113. type="primary"
  114. color="rgba(38, 151, 255, 1)"
  115. @click="importBtn"
  116. v-if="menuList.canImport"
  117. >导入</el-button
  118. >
  119. <el-button
  120. type="primary"
  121. style="margin-left: 0"
  122. color="rgba(48, 201, 191, 1)"
  123. @click="exportbtn"
  124. v-if="menuList.canExport"
  125. >导出</el-button
  126. >
  127. <el-button
  128. type="primary"
  129. style="margin-left: 0"
  130. color="rgba(38, 151, 255, 1)"
  131. @click="addlist"
  132. v-if="menuList.canInsert"
  133. >新增</el-button
  134. >
  135. </div>
  136. </div>
  137. <div class="footer" v-loading="loading">
  138. <el-table
  139. :row-class-name="tableRowClassName"
  140. :data="tableData.list"
  141. @selection-change="handleSelectionChange"
  142. style="width: 100%"
  143. :header-cell-style="{
  144. background: 'rgba(240, 243, 247, 1)',
  145. height: '50px',
  146. border: 0,
  147. }"
  148. >
  149. <!-- <el-table-column type="selection" align="center" width="55" /> -->
  150. <el-table-column align="center" prop="userName" label="姓名" />
  151. <el-table-column
  152. align="center"
  153. prop="identityTypeStr"
  154. width="100"
  155. label="身份认证"
  156. />
  157. <el-table-column
  158. align="center"
  159. prop="cardNumber"
  160. width="190"
  161. label="身份证号"
  162. />
  163. <el-table-column width="100" align="center" label="性别">
  164. <template #default="{ row }">
  165. <span>{{ row.genderStr }}</span>
  166. </template>
  167. </el-table-column>
  168. <el-table-column align="center" prop="periodName" label="入学年" />
  169. <el-table-column align="center" prop="graduateName" label="毕业年" />
  170. <el-table-column
  171. align="center"
  172. prop="collegeName"
  173. width="130"
  174. label="学院"
  175. />
  176. <el-table-column
  177. align="center"
  178. prop="majorName"
  179. width="150"
  180. label="专业"
  181. />
  182. <el-table-column
  183. align="center"
  184. prop="className"
  185. width="130"
  186. label="班级"
  187. />
  188. <el-table-column
  189. align="center"
  190. prop="phone"
  191. width="170"
  192. label="手机号码"
  193. />
  194. <el-table-column align="center" prop="employer" label="工作单位" />
  195. <el-table-column align="center" prop="status" label="工作地区">
  196. <template #default="{ row }">
  197. <span>{{ row.workloca }}</span>
  198. </template>
  199. </el-table-column>
  200. <el-table-column align="center" prop="position" label="职务" />
  201. <el-table-column
  202. align="center"
  203. prop="mailbox"
  204. label="邮箱"
  205. width="200"
  206. />
  207. <el-table-column
  208. align="center"
  209. label="操作"
  210. fixed="right"
  211. width="200"
  212. >
  213. <template #default="{ row }">
  214. <el-button
  215. v-if="menuList.canUpdate"
  216. type="primary"
  217. @click="updateS(row)"
  218. link
  219. >编辑</el-button
  220. >
  221. <el-button
  222. v-if="menuList.canDeleted"
  223. type="danger"
  224. @click="deleteS(row)"
  225. link
  226. >删除</el-button
  227. >
  228. </template>
  229. </el-table-column>
  230. </el-table>
  231. <!-- 分页组件 -->
  232. <div class="pageSize">
  233. <span></span>
  234. <el-pagination
  235. background
  236. :current-page="currentPage"
  237. :page-size="pageSize"
  238. :page-sizes="[10, 20, 30, 40]"
  239. layout="total,sizes, prev, pager, next, jumper, slot"
  240. :total="total"
  241. @size-change="handleSizeChange"
  242. @update:current-page="handleCurrentChange"
  243. />
  244. </div>
  245. </div>
  246. </div>
  247. <!-- 添加账号弹窗 -->
  248. <el-dialog
  249. class="addStaff"
  250. v-model="addDialogVisible"
  251. :close-on-click-modal="false"
  252. :close-on-press-escape="false"
  253. :title="dialongTitle"
  254. align-center
  255. width="560"
  256. :before-close="cancelAdd"
  257. destroy-on-close
  258. draggable
  259. >
  260. <el-form
  261. ref="ruleFormRef"
  262. :model="ruleForm"
  263. :rules="rules"
  264. label-width="100px"
  265. class="demo-ruleForm"
  266. :size="formSize"
  267. label-position="right"
  268. status-icon
  269. >
  270. <el-form-item label="姓名 :" prop="userName">
  271. <el-input
  272. clearable
  273. v-model.trim="ruleForm.userName"
  274. class="w-50 m-2"
  275. placeholder="请输入姓名"
  276. />
  277. </el-form-item>
  278. <el-form-item label="性别 :" prop="gender">
  279. <el-select
  280. clearable
  281. v-model="ruleForm.gender"
  282. placeholder="请选择性别"
  283. >
  284. <el-option label="男" :value="`男,1`" />
  285. <el-option label="女" :value="`女,2`" />
  286. </el-select>
  287. </el-form-item>
  288. <el-form-item label="身份认证 :" prop="identityType">
  289. <el-select
  290. clearable
  291. v-model="ruleForm.identityType"
  292. placeholder="请选择身份认证"
  293. >
  294. <el-option
  295. v-for="i in identityData"
  296. :key="i.id"
  297. :label="i.name"
  298. :value="`${i.name},${i.id}`"
  299. />
  300. </el-select>
  301. </el-form-item>
  302. <el-form-item label="身份证号 :" prop="cardNumber">
  303. <el-input
  304. clearable
  305. v-model.trim="ruleForm.cardNumber"
  306. class="w-50 m-2"
  307. placeholder="请输入身份证号"
  308. />
  309. </el-form-item>
  310. <el-form-item label="毕业年 :" prop="graduateId">
  311. <el-select
  312. clearable
  313. v-model="ruleForm.graduateId"
  314. placeholder="请选择毕业年"
  315. >
  316. <el-option
  317. v-for="i in graduateData"
  318. :key="i.id"
  319. :label="i.name"
  320. :value="`${i.name},${i.id}`"
  321. />
  322. </el-select>
  323. </el-form-item>
  324. <el-form-item label="所属学院 :" prop="collegeId">
  325. <el-select
  326. @change="collegeRuleChange"
  327. v-model="ruleForm.collegeId"
  328. clearable
  329. placeholder="请选择所属学院"
  330. >
  331. <el-option
  332. v-for="i in collegeData"
  333. :key="i.id"
  334. :label="i.name"
  335. :value="`${i.name},${i.id}`"
  336. />
  337. </el-select>
  338. </el-form-item>
  339. <el-form-item label="入学年 :" prop="periodId">
  340. <el-select
  341. @change="periodRuleChange"
  342. v-model="ruleForm.periodId"
  343. clearable
  344. placeholder="请选择入学年"
  345. >
  346. <el-option
  347. v-for="i in periodRuleData"
  348. :key="i.id"
  349. :label="i.name"
  350. :value="`${i.name},${i.id}`"
  351. />
  352. </el-select>
  353. </el-form-item>
  354. <el-form-item label="专业 :" prop="majorId">
  355. <el-select
  356. clearable
  357. v-model="ruleForm.majorId"
  358. placeholder="请选择专业"
  359. @change="majorRuleChange"
  360. >
  361. <el-option
  362. v-for="i in majorRuleData"
  363. :key="i.id"
  364. :label="i.name"
  365. :value="`${i.name},${i.id}`"
  366. />
  367. </el-select>
  368. </el-form-item>
  369. <el-form-item label="班级 :" prop="classId">
  370. <el-select
  371. clearable
  372. v-model="ruleForm.classId"
  373. placeholder="请选择班级"
  374. >
  375. <el-option
  376. v-for="i in classRuleData"
  377. :key="i.id"
  378. :label="i.name"
  379. :value="`${i.name},${i.id}`"
  380. />
  381. </el-select>
  382. </el-form-item>
  383. <el-form-item label="手机号码 :" prop="phone">
  384. <el-input
  385. clearable
  386. v-model.trim="ruleForm.phone"
  387. class="w-50 m-2"
  388. placeholder="请输入手机号码"
  389. />
  390. </el-form-item>
  391. <el-form-item label="工作单位 :" prop="employer">
  392. <el-input
  393. v-model.trim="ruleForm.employer"
  394. placeholder="请输入工作单位"
  395. clearable
  396. />
  397. </el-form-item>
  398. <el-form-item label="工作地区 :" prop="workloca">
  399. <el-input
  400. v-model.trim="ruleForm.workloca"
  401. placeholder="请输入工作地区"
  402. clearable
  403. />
  404. </el-form-item>
  405. <el-form-item label="职务 :" prop="position">
  406. <el-input
  407. v-model.trim="ruleForm.position"
  408. placeholder="请输入职务"
  409. clearable
  410. />
  411. </el-form-item>
  412. <el-form-item label="邮箱 :" prop="mailbox">
  413. <el-input
  414. v-model.trim="ruleForm.mailbox"
  415. placeholder="请输入邮箱"
  416. clearable
  417. />
  418. </el-form-item>
  419. <el-form-item class="options">
  420. <el-button @click="cancelAdd">取消</el-button>
  421. <el-button
  422. color="rgba(0, 97, 255, 1)"
  423. class="queding"
  424. type="primary"
  425. @click="submitAdd(ruleFormRef)"
  426. >
  427. 确定
  428. </el-button>
  429. </el-form-item>
  430. </el-form>
  431. </el-dialog>
  432. <!-- 项目导入 -->
  433. <el-dialog
  434. class="projectImport"
  435. v-model="buildImportVisible"
  436. :close-on-click-modal="false"
  437. :close-on-press-escape="false"
  438. title="校友信息导入"
  439. align-center
  440. width="500"
  441. :before-close="cancelProjectImport"
  442. >
  443. <!-- <p class="title">当前只支持项目类型为“非装配式建筑项目”的项目导入</p> -->
  444. <p class="down">
  445. <span>校友信息导入模板下载</span
  446. ><span @click="templateDown">模板下载</span>
  447. </p>
  448. <el-upload
  449. class="avatar-uploader"
  450. action="#"
  451. :auto-upload="false"
  452. :on-remove="projectImportRemove"
  453. :on-change="projectImportChange"
  454. :before-upload="beforeAvatarProImport"
  455. ref="buildRef"
  456. :limit="1"
  457. :on-exceed="projectImportExceed"
  458. >
  459. <template #trigger>
  460. <el-button class="queding" type="primary">
  461. &nbsp;&nbsp;导入文件&nbsp;&nbsp;
  462. </el-button>
  463. </template>
  464. </el-upload>
  465. <div class="options">
  466. <el-button
  467. color="rgba(9, 101, 98, 1)"
  468. class="queding"
  469. type="primary"
  470. @click="projectImportConfirm(buildRef)"
  471. :loading="buildImportLoading"
  472. >
  473. &nbsp;&nbsp;确认导入&nbsp;&nbsp;
  474. </el-button>
  475. <el-button @click="cancelProjectImport"
  476. >&nbsp;&nbsp;取消导入&nbsp;&nbsp;</el-button
  477. >
  478. </div>
  479. </el-dialog>
  480. </div>
  481. </template>
  482. <script setup>
  483. import {
  484. ref,
  485. watch,
  486. reactive,
  487. nextTick,
  488. onBeforeMount,
  489. onMounted,
  490. onUnmounted,
  491. } from "vue";
  492. import { useRouter } from "vue-router";
  493. import { genFileId, ElMessage, ElMessageBox } from "element-plus";
  494. import { dayjs } from "element-plus";
  495. import lodash from "lodash";
  496. import { storeToRefs } from "pinia";
  497. import { useCounterStore } from "@/stores/index";
  498. import {
  499. queryUsersPage,
  500. insertUserData,
  501. updateUserData,
  502. deleteUserDataById,
  503. downloadUserExcel,
  504. importUserExcel,
  505. alumniUserExport,
  506. queryGraduate,
  507. queryColleges,
  508. queryPeriods,
  509. queryMajors,
  510. queryClasses,
  511. queryIdentitys,
  512. } from "@/api/alumni-info.js";
  513. const router = useRouter();
  514. const store = useCounterStore();
  515. // 为避免解构时失去响应性
  516. const { name, age, isCollapse, realAge, collegeRole } = storeToRefs(store);
  517. const menuList = ref({
  518. canAll: null,
  519. canApply: null,
  520. canDeleted: null,
  521. canDetail: null,
  522. canExport: null,
  523. canImport: null,
  524. canInsert: null,
  525. canTop: null,
  526. canUpdate: null,
  527. canView: null,
  528. });
  529. // 表格数据
  530. const loading = ref(false);
  531. const tableData = reactive({
  532. list: [{}],
  533. });
  534. const dialongTitle = ref("新增账号"); // 弹窗标题
  535. const searchInput = reactive({
  536. name: "",
  537. collegeId: null,
  538. periodId: null,
  539. majorId: null,
  540. classId: null,
  541. identityType: "",
  542. }); // 搜索按钮数据
  543. const currentPage = ref(1); // 当前页
  544. const pageSize = ref(10);
  545. const total = ref(0); // 当前总数
  546. const selectIds = ref([]); // 勾选的全部数据
  547. const addDialogVisible = ref(false); // 控制添加账号弹窗
  548. // 表单数据
  549. const formSize = ref("default");
  550. const ruleFormRef = ref();
  551. const ruleForm = reactive({
  552. userName: "", //
  553. cardNumber: "", // 身份证号
  554. gender: "", // 性别ID
  555. identityType: "", // 身份认证ID
  556. graduateId: "", // 毕业年ID
  557. collegeId: "", // 学院ID
  558. periodId: "", // 入学年ID
  559. majorId: "", //专业ID
  560. classId: "", // 班级ID
  561. phone: "", // 手机号码
  562. employer: "", // 工作单位
  563. workloca: "", // 工作地区
  564. position: "", // 职务
  565. mailbox: "", // 邮箱
  566. id: "",
  567. });
  568. // 表单验证
  569. const rules = reactive({
  570. userName: [{ required: true, message: "姓名不能为空", trigger: "blur" }],
  571. cardNumber: [
  572. { required: true, message: "身份证号不能为空", trigger: "blur" },
  573. ],
  574. gender: [{ required: true, message: "性别不能为空", trigger: "blur" }],
  575. identityType: [
  576. { required: true, message: "身份认证不能为空", trigger: "blur" },
  577. ],
  578. graduateId: [{ required: true, message: "毕业年不能为空", trigger: "blur" }],
  579. collegeId: [{ required: true, message: "所属学院不能为空", trigger: "blur" }],
  580. periodId: [{ required: true, message: "入学年不能为空", trigger: "blur" }],
  581. majorId: [{ required: true, message: "专业不能为空", trigger: "blur" }],
  582. classId: [{ required: true, message: "班级不能为空", trigger: "blur" }],
  583. phone: [{ required: true, message: "手机号码不能为空", trigger: "blur" }],
  584. employer: [{ required: true, message: "工作单位不能为空", trigger: "blur" }],
  585. workloca: [{ required: true, message: "工作地区不能为空", trigger: "blur" }],
  586. position: [{ required: true, message: "职务不能为空", trigger: "blur" }],
  587. mailbox: [{ required: true, message: "邮箱不能为空", trigger: "blur" }],
  588. });
  589. // 导入
  590. const buildImportVisible = ref(false);
  591. const buildRef = ref();
  592. const buildFile = ref();
  593. const buildImportLoading = ref(false);
  594. // 学院
  595. const collegeData = ref([]);
  596. // 入学年
  597. const periodData = ref([]);
  598. // 专业
  599. const majorData = ref([]);
  600. // 班级
  601. const classData = ref([]);
  602. // 入学年
  603. const periodRuleData = ref([]);
  604. // 专业
  605. const majorRuleData = ref([]);
  606. // 班级
  607. const classRuleData = ref([]);
  608. // 身份认证
  609. const identityData = ref();
  610. // 毕业年份下拉
  611. const graduateData = ref();
  612. // 获取账户列表
  613. const getList = async () => {
  614. loading.value = true;
  615. let params = {
  616. currentPage: currentPage.value, // 当前页
  617. pageCount: pageSize.value, // 一页数据条数
  618. name: searchInput.name,
  619. collegeId: searchInput.collegeId,
  620. periodId: searchInput.periodId,
  621. majorId: searchInput.majorId,
  622. classId: searchInput.classId,
  623. identityType: searchInput.identityType,
  624. };
  625. queryUsersPage(params).then((res) => {
  626. console.log(res, "校友分页列表数据");
  627. if (res.code == 200) {
  628. tableData.list = res.data.list;
  629. total.value = res.data.totalCount;
  630. loading.value = false;
  631. } else {
  632. loading.value = false;
  633. ElMessage({
  634. type: "error",
  635. showClose: true,
  636. message: res.message,
  637. center: true,
  638. });
  639. }
  640. });
  641. };
  642. // 搜索功能
  643. const searchBtn = lodash.debounce(async () => {
  644. currentPage.value = 1;
  645. getList();
  646. }, 300);
  647. const resetBtn = lodash.debounce(async () => {
  648. searchInput.name = "";
  649. searchInput.collegeId = "";
  650. searchInput.periodId = "";
  651. periodData.value=[];
  652. searchInput.majorId = "";
  653. majorData.value=[];
  654. searchInput.classId = "";
  655. classData.value=[];
  656. searchInput.identityType = "";
  657. currentPage.value = 1;
  658. getList();
  659. }, 300);
  660. // 添加账号
  661. const addlist = () => {
  662. dialongTitle.value = "新增校友信息";
  663. addDialogVisible.value = true;
  664. // 逐个清空所有字段(统一设为空字符串,保持类型一致)
  665. ruleForm.userName = "";
  666. ruleForm.cardNumber = "";
  667. ruleForm.gender = "";
  668. ruleForm.identityType = "";
  669. ruleForm.graduateId = "";
  670. ruleForm.collegeId = "";
  671. ruleForm.periodId = "";
  672. ruleForm.majorId = "";
  673. ruleForm.classId = "";
  674. ruleForm.phone = "";
  675. ruleForm.employer = "";
  676. ruleForm.workloca = "";
  677. ruleForm.position = "";
  678. ruleForm.mailbox = "";
  679. ruleForm.id = "";
  680. // 清空表单校验状态(可选,需先定义 ruleFormRef)
  681. if (ruleFormRef.value) {
  682. ruleFormRef.value.clearValidate();
  683. }
  684. };
  685. // 添加账号
  686. const updateS = async (row) => {
  687. console.log(row);
  688. dialongTitle.value = "编辑校友信息";
  689. addDialogVisible.value = true;
  690. ruleForm.userName = row.userName || "";
  691. ruleForm.cardNumber = row.cardNumber || "";
  692. ruleForm.gender = `${row.genderStr},${row.gender}`;
  693. ruleForm.identityType = `${row.identityTypeStr},${row.identityType}`;
  694. ruleForm.graduateId = `${row.graduateName},${row.graduateId}`;
  695. ruleForm.collegeId = `${row.collegeName},${row.collegeId}`;
  696. // 入学年
  697. {
  698. if (row.collegeId) {
  699. let params = {
  700. collegeId: row.collegeId,
  701. };
  702. let res = await queryPeriods(params);
  703. if (res.code == 200) {
  704. periodRuleData.value = res.data;
  705. ruleForm.periodId = `${row.periodName},${row.periodId}`;
  706. } else {
  707. ElMessage({
  708. type: "error",
  709. showClose: true,
  710. message: res.message,
  711. center: true,
  712. });
  713. }
  714. }
  715. }
  716. // 专业
  717. {
  718. if (row.periodId) {
  719. let params = {
  720. periodId: row.periodId,
  721. };
  722. let res = await queryMajors(params);
  723. console.log(res, "专业下拉列表数据");
  724. if (res.code == 200) {
  725. majorRuleData.value = res.data;
  726. ruleForm.majorId = `${row.majorName},${row.majorId}`;
  727. } else {
  728. ElMessage({
  729. type: "error",
  730. showClose: true,
  731. message: res.message,
  732. center: true,
  733. });
  734. }
  735. }
  736. }
  737. // 班级
  738. {
  739. if (row.majorId) {
  740. let params = {
  741. majorId: row.majorId,
  742. };
  743. let res = await queryClasses(params);
  744. console.log(res, "班级下拉列表数据");
  745. if (res.code == 200) {
  746. classRuleData.value = res.data;
  747. ruleForm.classId = `${row.className},${row.classId}`;
  748. } else {
  749. ElMessage({
  750. type: "error",
  751. showClose: true,
  752. message: res.message,
  753. center: true,
  754. });
  755. }
  756. }
  757. }
  758. ruleForm.phone = row.phone || "";
  759. ruleForm.employer = row.employer || "";
  760. ruleForm.workloca = row.workloca || "";
  761. ruleForm.position = row.position || "";
  762. ruleForm.mailbox = row.mailbox || "";
  763. ruleForm.id = row.id || "";
  764. };
  765. const deleteS = async (row) => {
  766. ElMessageBox.confirm("是否删除此数据?", "提示!!!", {
  767. confirmButtonText: "确认",
  768. cancelButtonText: "取消",
  769. type: "warning",
  770. })
  771. .then(async () => {
  772. let params = {
  773. id: row.id,
  774. };
  775. let res = await deleteUserDataById(params);
  776. if (res.code == 200) {
  777. getList();
  778. ElMessage({
  779. type: "success",
  780. showClose: true,
  781. message: res.message,
  782. center: true,
  783. });
  784. } else {
  785. ElMessage({
  786. type: "error",
  787. showClose: true,
  788. message: res.message,
  789. center: true,
  790. });
  791. }
  792. })
  793. .catch(() => {
  794. loading.value = false;
  795. });
  796. };
  797. // 确认添加员工
  798. const submitAdd = lodash.debounce(async (formEl) => {
  799. if (!formEl) return;
  800. await formEl.validate(async (valid, fields) => {
  801. if (valid) {
  802. let data = {
  803. userName: ruleForm.userName,
  804. cardNumber: ruleForm.cardNumber,
  805. gender: ruleForm.gender.split(",")[1],
  806. genderStr: ruleForm.gender.split(",")[0],
  807. identityType: ruleForm.identityType.split(",")[1],
  808. identityTypeStr: ruleForm.identityType.split(",")[0],
  809. graduateId: ruleForm.graduateId.split(",")[1],
  810. graduateName: ruleForm.graduateId.split(",")[0],
  811. collegeId: ruleForm.collegeId.split(",")[1],
  812. collegeName: ruleForm.collegeId.split(",")[0],
  813. periodId: ruleForm.periodId.split(",")[1],
  814. periodName: ruleForm.periodId.split(",")[0],
  815. majorId: ruleForm.majorId.split(",")[1],
  816. majorName: ruleForm.majorId.split(",")[0],
  817. classId: ruleForm.classId.split(",")[1],
  818. className: ruleForm.classId.split(",")[0],
  819. phone: ruleForm.phone,
  820. employer: ruleForm.employer,
  821. workloca: ruleForm.workloca,
  822. position: ruleForm.position,
  823. mailbox: ruleForm.mailbox,
  824. };
  825. let res = "";
  826. if (dialongTitle.value == "新增校友信息") {
  827. res = await insertUserData(data);
  828. } else {
  829. data.id = ruleForm.id;
  830. res = await updateUserData(data);
  831. }
  832. if (res.code == 200) {
  833. addDialogVisible.value = false;
  834. ElMessage({
  835. type: "success",
  836. showClose: true,
  837. message: res.message,
  838. center: true,
  839. });
  840. getList();
  841. } else {
  842. ElMessage({
  843. type: "error",
  844. showClose: true,
  845. message: res.message,
  846. center: true,
  847. });
  848. }
  849. } else {
  850. console.log("error submit!", fields);
  851. }
  852. });
  853. }, 1000);
  854. const cancelAdd = () => {
  855. addDialogVisible.value = false;
  856. };
  857. // 多选框功能
  858. const handleSelectionChange = (val) => {
  859. // console.log(val);
  860. selectIds.value = val.map((i) => i.id);
  861. console.log(selectIds.value);
  862. };
  863. // 表格斑马纹颜色修改
  864. const tableRowClassName = ({ row, rowIndex }) => {
  865. if (rowIndex % 2 === 0) {
  866. return "even";
  867. } else if (rowIndex % 2 !== 0) {
  868. return "odd";
  869. }
  870. return "";
  871. };
  872. // 每页显示条数
  873. const handleSizeChange = (value) => {
  874. console.log(value, "每页显示条数");
  875. pageSize.value = value;
  876. getList();
  877. };
  878. // 分页
  879. const handleCurrentChange = (value) => {
  880. // console.log(value);
  881. currentPage.value = value;
  882. getList();
  883. };
  884. // 楼栋导出
  885. const exportbtn = async () => {
  886. try {
  887. const params = {
  888. name: searchInput.name,
  889. collegeId: searchInput.collegeId,
  890. periodId: searchInput.periodId,
  891. majorId: searchInput.majorId,
  892. classId: searchInput.classId,
  893. identityType: searchInput.identityType,
  894. };
  895. // 1. 请求接口获取流数据
  896. const res = await alumniUserExport(params);
  897. console.log(res, "校友信息管理导出");
  898. // 2. 处理流数据:转为 Blob 对象(判断是否是已解析的 Blob,兼容不同封装)
  899. const blob =
  900. res instanceof Blob
  901. ? res
  902. : new Blob([res], {
  903. type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // Excel MIME 类型
  904. });
  905. // 3. 提取后端返回的文件名(从响应头获取,若无则用默认名)
  906. let fileName = "校友信息导出.xlsx";
  907. // 如果后端在响应头返回了文件名(如 Content-Disposition),解析它
  908. if (res.headers?.["content-disposition"]) {
  909. const disposition = res.headers["content-disposition"];
  910. fileName = decodeURIComponent(
  911. disposition.split("filename=")[1] || fileName,
  912. );
  913. }
  914. // 4. 创建临时下载链接并触发下载
  915. const url = window.URL.createObjectURL(blob);
  916. const link = document.createElement("a");
  917. link.href = url;
  918. link.download = fileName; // 设置下载文件名
  919. document.body.appendChild(link);
  920. link.click(); // 触发点击下载
  921. // 5. 清理临时资源,避免内存泄漏
  922. document.body.removeChild(link);
  923. window.URL.revokeObjectURL(url);
  924. ElMessage.success("导出成功,文件已开始下载");
  925. } catch (error) {
  926. console.error("导出失败:", error);
  927. ElMessage.error("导出失败,请重试");
  928. }
  929. };
  930. // 楼栋导入 (--------------------------------------------------)
  931. const importBtn = () => {
  932. buildImportVisible.value = true;
  933. buildFile.value = "";
  934. if (buildRef.value) {
  935. buildRef.value.clearFiles();
  936. }
  937. };
  938. // 模板下载
  939. const templateDown = async () => {
  940. let res = await downloadUserExcel();
  941. console.log(res, "模板下载");
  942. if (res.code == 200) {
  943. window.location.href = res.data;
  944. } else {
  945. ElMessage({
  946. type: "error",
  947. showClose: true,
  948. message: res.message,
  949. center: true,
  950. });
  951. }
  952. };
  953. // 移出照片
  954. const projectImportRemove = (uploadFile, uploadFiles) => {
  955. console.log(uploadFile, uploadFiles);
  956. buildFile.value = "";
  957. };
  958. const projectImportChange = async (file, fileLists) => {
  959. console.log(file, "1111");
  960. buildFile.value = file.raw;
  961. };
  962. const projectImportExceed = (files) => {
  963. buildRef.value.clearFiles();
  964. const file = files[0];
  965. file.uid = genFileId();
  966. buildRef.value.handleStart(file);
  967. };
  968. // 导入项目
  969. const projectImportConfirm = async () => {
  970. buildImportLoading.value = true;
  971. console.log(buildFile.value, "2222");
  972. let data = new FormData();
  973. data.set("file", buildFile.value);
  974. let res = await importUserExcel(data);
  975. console.log(res, "导入校友信息");
  976. if (res.code == 200) {
  977. buildImportVisible.value = false;
  978. buildImportLoading.value = false;
  979. getList();
  980. ElMessage({
  981. type: "success",
  982. showClose: true,
  983. message: res.message,
  984. center: true,
  985. });
  986. } else {
  987. buildImportLoading.value = false;
  988. ElMessage({
  989. type: "error",
  990. showClose: true,
  991. message: res.message,
  992. center: true,
  993. });
  994. }
  995. };
  996. const cancelProjectImport = () => {
  997. buildImportVisible.value = false;
  998. buildImportLoading.value = false;
  999. if (buildRef.value) {
  1000. buildRef.value.clearFiles();
  1001. buildFile.value = null;
  1002. }
  1003. };
  1004. // 学院下拉列表数据
  1005. const collegeList = async () => {
  1006. let res = await queryColleges();
  1007. console.log(res, "学院下拉列表数据");
  1008. if (res.code == 200) {
  1009. collegeData.value = res.data;
  1010. } else {
  1011. ElMessage({
  1012. type: "error",
  1013. showClose: true,
  1014. message: res.message,
  1015. center: true,
  1016. });
  1017. }
  1018. };
  1019. // 入学年下拉列表数据
  1020. const collegeChange = async (val) => {
  1021. let params = {
  1022. collegeId: val,
  1023. };
  1024. let res = await queryPeriods(params);
  1025. console.log(res, "入学年下拉列表数据");
  1026. if (res.code == 200) {
  1027. periodData.value = res.data;
  1028. searchInput.periodId = ""; // 入学年
  1029. majorData.value = []; // 专业
  1030. searchInput.majorId = ""; // 专业
  1031. classData.value = []; // 班级
  1032. searchInput.classId = ""; // 班级
  1033. } else {
  1034. ElMessage({
  1035. type: "error",
  1036. showClose: true,
  1037. message: res.message,
  1038. center: true,
  1039. });
  1040. }
  1041. };
  1042. // 专业下拉列表数据
  1043. const periodChange = async (val) => {
  1044. let params = {
  1045. periodId: val,
  1046. };
  1047. let res = await queryMajors(params);
  1048. console.log(res, "专业下拉列表数据");
  1049. if (res.code == 200) {
  1050. majorData.value = res.data;
  1051. searchInput.majorId = ""; // 专业
  1052. classData.value = []; // 班级
  1053. searchInput.classId = ""; // 班级
  1054. } else {
  1055. ElMessage({
  1056. type: "error",
  1057. showClose: true,
  1058. message: res.message,
  1059. center: true,
  1060. });
  1061. }
  1062. };
  1063. // 班级下拉列表数据
  1064. const majorChange = async (val) => {
  1065. let params = {
  1066. majorId: val,
  1067. };
  1068. let res = await queryClasses(params);
  1069. console.log(res, "班级下拉列表数据");
  1070. if (res.code == 200) {
  1071. classData.value = res.data;
  1072. searchInput.classId = ""; // 班级
  1073. } else {
  1074. ElMessage({
  1075. type: "error",
  1076. showClose: true,
  1077. message: res.message,
  1078. center: true,
  1079. });
  1080. }
  1081. };
  1082. // 入学年下拉列表数据
  1083. const collegeRuleChange = async (val) => {
  1084. let params = {
  1085. collegeId: val.split(",")[1],
  1086. };
  1087. let res = await queryPeriods(params);
  1088. console.log(res, "入学年下拉列表数据");
  1089. if (res.code == 200) {
  1090. periodRuleData.value = res.data;
  1091. ruleForm.periodId = ""; // 入学年
  1092. majorRuleData.value = []; // 专业
  1093. ruleForm.majorId = ""; // 专业
  1094. classRuleData.value = []; // 班级
  1095. ruleForm.classId = ""; // 班级
  1096. } else {
  1097. ElMessage({
  1098. type: "error",
  1099. showClose: true,
  1100. message: res.message,
  1101. center: true,
  1102. });
  1103. }
  1104. };
  1105. // 专业下拉列表数据
  1106. const periodRuleChange = async (val) => {
  1107. let params = {
  1108. periodId: val.split(",")[1],
  1109. };
  1110. let res = await queryMajors(params);
  1111. console.log(res, "专业下拉列表数据");
  1112. if (res.code == 200) {
  1113. majorRuleData.value = res.data;
  1114. ruleForm.majorId = ""; // 专业
  1115. classRuleData.value = []; // 班级
  1116. ruleForm.classId = ""; // 班级
  1117. } else {
  1118. ElMessage({
  1119. type: "error",
  1120. showClose: true,
  1121. message: res.message,
  1122. center: true,
  1123. });
  1124. }
  1125. };
  1126. // 班级下拉列表数据
  1127. const majorRuleChange = async (val) => {
  1128. let params = {
  1129. majorId: val.split(",")[1],
  1130. };
  1131. let res = await queryClasses(params);
  1132. console.log(res, "班级下拉列表数据");
  1133. if (res.code == 200) {
  1134. classRuleData.value = res.data;
  1135. ruleForm.classId = ""; // 班级
  1136. } else {
  1137. ElMessage({
  1138. type: "error",
  1139. showClose: true,
  1140. message: res.message,
  1141. center: true,
  1142. });
  1143. }
  1144. };
  1145. // 身份认证下拉列表数据
  1146. const identityList = async (val) => {
  1147. let res = await queryIdentitys();
  1148. console.log(res, "身份认证下拉列表数据");
  1149. if (res.code == 200) {
  1150. identityData.value = res.data;
  1151. } else {
  1152. ElMessage({
  1153. type: "error",
  1154. showClose: true,
  1155. message: res.message,
  1156. center: true,
  1157. });
  1158. }
  1159. };
  1160. // 毕业年份下拉列表数据
  1161. const graduateList = async () => {
  1162. let res = await queryGraduate();
  1163. console.log(res, "毕业年份下拉列表数据");
  1164. if (res.code == 200) {
  1165. graduateData.value = res.data;
  1166. } else {
  1167. ElMessage({
  1168. type: "error",
  1169. showClose: true,
  1170. message: res.message,
  1171. center: true,
  1172. });
  1173. }
  1174. };
  1175. onMounted(() => {
  1176. getList();
  1177. collegeList();
  1178. identityList();
  1179. graduateList();
  1180. let list = JSON.parse(sessionStorage.getItem("roleList"));
  1181. console.log(list);
  1182. list.forEach((i) => {
  1183. if (i.menuName == "校友信息管理") {
  1184. i.childs.forEach((item) => {
  1185. if (item.menuName == "校友信息管理") {
  1186. menuList.value = item;
  1187. }
  1188. });
  1189. }
  1190. });
  1191. console.log(menuList.value);
  1192. });
  1193. onUnmounted(() => {
  1194. // document.removeEventListener("keyup", Enters);
  1195. });
  1196. </script>
  1197. <style scoped lang="scss">
  1198. .content-box {
  1199. width: calc(100% - 40px);
  1200. height: calc(100% - 105px);
  1201. margin: 20px auto;
  1202. background-color: #fff;
  1203. color: #000;
  1204. display: flex;
  1205. flex-direction: column;
  1206. .svg {
  1207. width: 22px;
  1208. height: 22px;
  1209. }
  1210. .left {
  1211. width: calc(100% - 60px);
  1212. height: 60px;
  1213. margin: 0 auto;
  1214. display: flex;
  1215. align-items: center;
  1216. border-bottom: 1px solid #ccc;
  1217. color: #000;
  1218. font-size: 18px;
  1219. font-weight: 600;
  1220. .camera {
  1221. margin-right: 15px;
  1222. color: #4392f7;
  1223. }
  1224. }
  1225. .scroll {
  1226. width: calc(100% - 60px);
  1227. height: calc(100% - 61px);
  1228. margin: 0 auto;
  1229. display: flex;
  1230. flex-direction: column;
  1231. .middle {
  1232. width: calc(100%);
  1233. color: #000;
  1234. .filter {
  1235. display: flex;
  1236. flex-wrap: wrap;
  1237. align-items: center;
  1238. .search {
  1239. margin-left: 0 !important;
  1240. color: #fff;
  1241. }
  1242. .condition {
  1243. display: flex;
  1244. align-items: center;
  1245. margin: 10px 30px 10px 0;
  1246. :deep(.el-input .el-input__inner) {
  1247. font-size: 14px;
  1248. }
  1249. .el-select {
  1250. width: 220px;
  1251. }
  1252. span {
  1253. margin: 0 10px 0 0;
  1254. }
  1255. }
  1256. }
  1257. .gongneng {
  1258. margin: 10px 0;
  1259. .el-button {
  1260. color: #fff;
  1261. margin-right: 15px;
  1262. }
  1263. }
  1264. }
  1265. .footer {
  1266. width: calc(100%);
  1267. flex: 1;
  1268. margin: 0 auto;
  1269. overflow: auto;
  1270. .el-table--fit {
  1271. height: calc(100% - 60px);
  1272. :deep(.el-table__header-wrapper) {
  1273. background-color: #000;
  1274. font-size: 15px;
  1275. color: #000;
  1276. .cell {
  1277. color: #000;
  1278. }
  1279. }
  1280. :deep(.el-table__row) {
  1281. height: 50px;
  1282. font-size: 15px;
  1283. color: #000;
  1284. }
  1285. :deep(.el-table__row td) {
  1286. padding: 0;
  1287. border: 0;
  1288. }
  1289. .el-button--primary {
  1290. margin-left: 5px;
  1291. }
  1292. :deep(.el-table__body .even) {
  1293. background-color: #fff;
  1294. }
  1295. :deep(.el-table__body .odd) {
  1296. background-color: rgba(240, 243, 247, 1);
  1297. }
  1298. }
  1299. .pageSize {
  1300. display: flex;
  1301. align-items: center;
  1302. justify-content: space-between;
  1303. margin: 0 30px;
  1304. height: 60px;
  1305. span {
  1306. color: #000;
  1307. }
  1308. .el-pagination {
  1309. // width: 1600px;
  1310. :deep(.el-pagination__total) {
  1311. color: #000;
  1312. }
  1313. :deep(.el-pagination__goto) {
  1314. color: #000;
  1315. }
  1316. :deep(.el-pagination__classifier) {
  1317. color: #000;
  1318. }
  1319. :deep(.el-input__wrapper) {
  1320. border: 1px solid rgba(0, 0, 0, 1);
  1321. border-radius: 5px;
  1322. box-shadow: none;
  1323. }
  1324. :deep(.el-pager li) {
  1325. margin: 0 5px;
  1326. border: 1px solid rgba(0, 0, 0, 1);
  1327. border-radius: 5px;
  1328. background-color: transparent;
  1329. }
  1330. :deep(.el-pager li.is-active) {
  1331. // background-color: rgba(0, 97, 255, 0.8);
  1332. border: 1px solid rgba(0, 97, 255, 1);
  1333. color: rgba(0, 97, 255, 1);
  1334. }
  1335. :deep(.btn-prev) {
  1336. margin-right: 5px;
  1337. border: 1px solid rgba(0, 0, 0, 1);
  1338. border-radius: 5px;
  1339. background-color: transparent;
  1340. }
  1341. :deep(.btn-next) {
  1342. margin-left: 5px;
  1343. border: 1px solid rgba(0, 0, 0, 1);
  1344. border-radius: 5px;
  1345. background-color: transparent;
  1346. }
  1347. }
  1348. }
  1349. }
  1350. }
  1351. // 添加员工弹窗样式
  1352. :deep(.addStaff) {
  1353. .el-dialog__body {
  1354. padding: 20px 20px 10px 20px;
  1355. .el-input {
  1356. width: 400px;
  1357. .el-input__suffix-inner {
  1358. color: rgba(61, 81, 232, 1);
  1359. }
  1360. }
  1361. .el-select {
  1362. width: 400px;
  1363. }
  1364. .el-tree {
  1365. width: 400px;
  1366. }
  1367. }
  1368. }
  1369. // 导入
  1370. :deep(.projectImport) {
  1371. .el-dialog__body {
  1372. padding: 20px 30px 0 30px;
  1373. .title {
  1374. color: red;
  1375. }
  1376. .down {
  1377. span:nth-child(1) {
  1378. color: rgba(127, 127, 127, 1);
  1379. }
  1380. span:nth-child(2) {
  1381. margin-left: 25px;
  1382. color: rgba(2, 167, 240, 1);
  1383. cursor: pointer;
  1384. }
  1385. }
  1386. .options {
  1387. margin: 50px 0 30px 0;
  1388. display: flex;
  1389. flex-direction: row-reverse;
  1390. .queding {
  1391. margin-left: 20px;
  1392. background: linear-gradient(
  1393. 90deg,
  1394. rgba(38, 151, 255, 1) 0%,
  1395. rgba(102, 181, 255, 1) 100%
  1396. );
  1397. border: none;
  1398. }
  1399. .quxiao {
  1400. border: 1px solid rgba(43, 151, 252, 1);
  1401. color: rgba(43, 151, 252, 1);
  1402. }
  1403. }
  1404. }
  1405. }
  1406. }
  1407. </style>