AssociateCampusDialog.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. <template>
  2. <el-dialog
  3. title="关联校区"
  4. v-model="visible"
  5. width="500px"
  6. append-to-body
  7. align-center
  8. :center="true"
  9. :destroy-on-close="true"
  10. >
  11. <div class="associate-campus-content">
  12. <el-form
  13. ref="associateCampusFormRef"
  14. :model="form"
  15. :rules="rules"
  16. label-width="100px"
  17. >
  18. <!-- 卡号段 -->
  19. <el-form-item label="卡号段" :required="true">
  20. <div style="display: flex; align-items: center; gap: 10px">
  21. <el-form-item prop="beginCardNo" style="flex: 1; margin-bottom: 0">
  22. <el-input
  23. v-model="form.beginCardNo"
  24. placeholder="开始卡号"
  25. style="width: 100%"
  26. />
  27. </el-form-item>
  28. <span>-</span>
  29. <el-form-item prop="endCardNo" style="flex: 1; margin-bottom: 0">
  30. <el-input
  31. v-model="form.endCardNo"
  32. placeholder="结束卡号"
  33. style="width: 100%"
  34. />
  35. </el-form-item>
  36. </div>
  37. </el-form-item>
  38. <!-- 校区 -->
  39. <el-form-item label="校区" prop="campusId" :required="true">
  40. <el-select
  41. v-model="form.campusId"
  42. placeholder="请选择校区"
  43. style="width: 100%"
  44. >
  45. <el-option
  46. v-for="campus in campusList"
  47. :key="campus.id"
  48. :label="campus.name"
  49. :value="campus.id"
  50. ></el-option>
  51. </el-select>
  52. </el-form-item>
  53. </el-form>
  54. </div>
  55. <template #footer>
  56. <div class="dialog-footer">
  57. <el-button @click="handleCancel">取消</el-button>
  58. <el-button type="primary" @click="handleConfirm" :loading="loading">
  59. <svg-icon
  60. icon-class="lightning"
  61. class="mr-1"
  62. style="font-size: 14px"
  63. />
  64. 确认
  65. </el-button>
  66. </div>
  67. </template>
  68. </el-dialog>
  69. </template>
  70. <script setup>
  71. import { ref, computed, watch } from "vue";
  72. import { associateCampus, getCampusList } from "@/api/dz/cards";
  73. const props = defineProps({
  74. modelValue: {
  75. type: Boolean,
  76. default: false,
  77. },
  78. selectedCards: {
  79. type: Array,
  80. default: () => [],
  81. },
  82. });
  83. const emit = defineEmits(["update:modelValue", "confirm", "success"]);
  84. const visible = computed({
  85. get: () => props.modelValue,
  86. set: (value) => emit("update:modelValue", value),
  87. });
  88. const associateCampusFormRef = ref();
  89. const loading = ref(false);
  90. const campusList = ref([]);
  91. const form = ref({
  92. beginCardNo: "",
  93. endCardNo: "",
  94. campusId: null,
  95. });
  96. const rules = {
  97. beginCardNo: [
  98. { required: true, message: "开始卡号不能为空", trigger: "blur" },
  99. ],
  100. endCardNo: [{ required: true, message: "结束卡号不能为空", trigger: "blur" }],
  101. campusId: [{ required: true, message: "校区不能为空", trigger: "change" }],
  102. };
  103. // 获取校区列表
  104. async function getCampusListData() {
  105. try {
  106. const response = await getCampusList({
  107. pageNum: 1,
  108. pageSize: 9999, // 获取所有校区
  109. });
  110. if (response.code === 200) {
  111. // 处理API返回的数据结构
  112. let campusData = [];
  113. if (response.data) {
  114. campusData = Array.isArray(response.data) ? response.data : [];
  115. } else if (response.rows) {
  116. campusData = response.rows;
  117. } else if (response.list) {
  118. campusData = response.list;
  119. }
  120. // 确保数据格式符合配置要求
  121. campusData = campusData.map((item) => {
  122. // 如果API返回的是 {id, name, ...} 格式,直接使用
  123. if (item.id && item.name) {
  124. return item;
  125. }
  126. // 如果是其他格式,需要转换
  127. return {
  128. id: item.id || item.value || item.campusId,
  129. name: item.name || item.label || item.campusName || item.title,
  130. };
  131. });
  132. campusList.value = campusData;
  133. }
  134. } catch (error) {
  135. console.error("获取校区列表失败:", error);
  136. campusList.value = [];
  137. }
  138. }
  139. // 自动填充卡号段
  140. function autoFillCardRange() {
  141. if (props.selectedCards && props.selectedCards.length > 0) {
  142. const cardNos = props.selectedCards
  143. .map((card) => card.cardNo || card.id)
  144. .filter((cardNo) => cardNo && cardNo !== "未知")
  145. .sort();
  146. if (cardNos.length > 0) {
  147. const minCardNo = cardNos[0];
  148. const maxCardNo = cardNos[cardNos.length - 1];
  149. // 开始卡号段是最小卡号段的整十数部分
  150. const minCardNoNum = parseInt(minCardNo);
  151. const beginCardNo = Math.floor(minCardNoNum / 10) * 10;
  152. form.value.beginCardNo = beginCardNo.toString();
  153. form.value.endCardNo = maxCardNo;
  154. }
  155. }
  156. }
  157. // 重置表单
  158. function resetForm() {
  159. form.value = {
  160. beginCardNo: "",
  161. endCardNo: "",
  162. campusId: null,
  163. };
  164. }
  165. // 取消
  166. function handleCancel() {
  167. visible.value = false;
  168. resetForm();
  169. }
  170. // 确认关联
  171. async function handleConfirm() {
  172. associateCampusFormRef.value.validate(async (valid) => {
  173. if (valid) {
  174. try {
  175. loading.value = true;
  176. const begin = form.value.beginCardNo;
  177. const end = form.value.endCardNo;
  178. const campusId = form.value.campusId;
  179. if (!begin || !end) {
  180. throw new Error("请填写完整的卡号段");
  181. }
  182. if (!campusId) {
  183. throw new Error("请选择校区");
  184. }
  185. await associateCampus(begin, end, campusId);
  186. emit("success", "关联校区成功!");
  187. visible.value = false;
  188. resetForm();
  189. } catch (error) {
  190. console.error("关联校区失败:", error);
  191. emit("confirm", { error: error.message });
  192. } finally {
  193. loading.value = false;
  194. }
  195. }
  196. });
  197. }
  198. // 监听弹窗关闭,重置表单
  199. watch(visible, (newVal) => {
  200. if (!newVal) {
  201. resetForm();
  202. } else {
  203. getCampusListData();
  204. autoFillCardRange();
  205. }
  206. });
  207. </script>
  208. <style scoped>
  209. .associate-campus-content {
  210. padding: 20px 0;
  211. }
  212. .hint-text {
  213. color: #1890ff;
  214. font-size: 12px;
  215. margin-bottom: 20px;
  216. padding-left: 100px;
  217. }
  218. .dialog-footer {
  219. text-align: right;
  220. }
  221. </style>