AssociateCampusDialog.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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 label="全部" value="all"></el-option>
  46. <el-option
  47. v-for="campus in campusList"
  48. :key="campus.id"
  49. :label="campus.name"
  50. :value="campus.id"
  51. ></el-option>
  52. </el-select>
  53. </el-form-item>
  54. </el-form>
  55. </div>
  56. <template #footer>
  57. <div class="dialog-footer">
  58. <el-button @click="handleCancel">取消</el-button>
  59. <el-button type="primary" @click="handleConfirm" :loading="loading">
  60. <svg-icon
  61. icon-class="lightning"
  62. class="mr-1"
  63. style="font-size: 14px"
  64. />
  65. 确认
  66. </el-button>
  67. </div>
  68. </template>
  69. </el-dialog>
  70. </template>
  71. <script setup>
  72. import { ref, computed, watch } from "vue";
  73. import { associateCampus, getCampusList } from "@/api/dz/cards";
  74. const props = defineProps({
  75. modelValue: {
  76. type: Boolean,
  77. default: false,
  78. },
  79. selectedCards: {
  80. type: Array,
  81. default: () => [],
  82. },
  83. });
  84. const emit = defineEmits(["update:modelValue", "confirm", "success"]);
  85. const visible = computed({
  86. get: () => props.modelValue,
  87. set: (value) => emit("update:modelValue", value),
  88. });
  89. const associateCampusFormRef = ref();
  90. const loading = ref(false);
  91. const campusList = ref([]);
  92. const form = ref({
  93. beginCardNo: "",
  94. endCardNo: "",
  95. campusId: null,
  96. });
  97. const rules = {
  98. beginCardNo: [
  99. { required: true, message: "开始卡号不能为空", trigger: "blur" },
  100. ],
  101. endCardNo: [{ required: true, message: "结束卡号不能为空", trigger: "blur" }],
  102. campusId: [{ required: true, message: "校区不能为空", trigger: "change" }],
  103. };
  104. // 获取校区列表
  105. async function getCampusListData() {
  106. try {
  107. const response = await getCampusList({ pageNum: 1, pageSize: 1000 });
  108. if (response.code === 200) {
  109. campusList.value = response.data || [];
  110. }
  111. } catch (error) {
  112. console.error("获取校区列表失败:", error);
  113. }
  114. }
  115. // 自动填充卡号段
  116. function autoFillCardRange() {
  117. if (props.selectedCards && props.selectedCards.length > 0) {
  118. const cardNos = props.selectedCards
  119. .map((card) => card.cardNo || card.id)
  120. .filter((cardNo) => cardNo && cardNo !== "未知")
  121. .sort();
  122. if (cardNos.length > 0) {
  123. const minCardNo = cardNos[0];
  124. const maxCardNo = cardNos[cardNos.length - 1];
  125. // 开始卡号段是最小卡号段的整十数部分
  126. const minCardNoNum = parseInt(minCardNo);
  127. const beginCardNo = Math.floor(minCardNoNum / 10) * 10;
  128. form.value.beginCardNo = beginCardNo.toString();
  129. form.value.endCardNo = maxCardNo;
  130. }
  131. }
  132. }
  133. // 重置表单
  134. function resetForm() {
  135. form.value = {
  136. beginCardNo: "",
  137. endCardNo: "",
  138. campusId: null,
  139. };
  140. }
  141. // 取消
  142. function handleCancel() {
  143. visible.value = false;
  144. resetForm();
  145. }
  146. // 确认关联
  147. async function handleConfirm() {
  148. associateCampusFormRef.value.validate(async (valid) => {
  149. if (valid) {
  150. try {
  151. loading.value = true;
  152. const begin = form.value.beginCardNo;
  153. const end = form.value.endCardNo;
  154. const campusId = form.value.campusId;
  155. if (!begin || !end) {
  156. throw new Error("请填写完整的卡号段");
  157. }
  158. if (!campusId || campusId === "all") {
  159. throw new Error("请选择校区");
  160. }
  161. await associateCampus(begin, end, campusId);
  162. emit("success", "关联校区成功!");
  163. visible.value = false;
  164. resetForm();
  165. } catch (error) {
  166. console.error("关联校区失败:", error);
  167. emit("confirm", { error: error.message });
  168. } finally {
  169. loading.value = false;
  170. }
  171. }
  172. });
  173. }
  174. // 监听弹窗关闭,重置表单
  175. watch(visible, (newVal) => {
  176. if (!newVal) {
  177. resetForm();
  178. } else {
  179. getCampusListData();
  180. autoFillCardRange();
  181. }
  182. });
  183. </script>
  184. <style scoped>
  185. .associate-campus-content {
  186. padding: 20px 0;
  187. }
  188. .hint-text {
  189. color: #1890ff;
  190. font-size: 12px;
  191. margin-bottom: 20px;
  192. padding-left: 100px;
  193. }
  194. .dialog-footer {
  195. text-align: right;
  196. }
  197. </style>