select-student.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. <template>
  2. <div>
  3. <el-form :model="form" ref="form" label-suffix=": " inline>
  4. <el-row>
  5. <el-col :span="10" v-if="showName">
  6. <el-form-item
  7. label="班级名称"
  8. prop="name"
  9. :rules="[
  10. { required: true, message: '请输入班级名称', trigger: 'blur' },
  11. ]"
  12. >
  13. <el-input
  14. v-model="form.name"
  15. style="width: 100%"
  16. placeholder="请输入班级名称"
  17. />
  18. </el-form-item>
  19. </el-col>
  20. <el-col :span="10" :offset="showName ? 4 : 0">
  21. <el-form-item label="声部">
  22. <el-select
  23. v-model="sound"
  24. style="width: 100%"
  25. clearable
  26. multiple
  27. collapse-tags
  28. filterable
  29. placeholder="请选择声部"
  30. >
  31. <el-option
  32. v-for="(item, index) in soundList"
  33. :key="index"
  34. :label="item.name"
  35. :value="item.id"
  36. ></el-option>
  37. </el-select>
  38. </el-form-item>
  39. </el-col>
  40. </el-row>
  41. <el-transfer
  42. filterable
  43. :titles="['所有学员', '已选学员']"
  44. filter-placeholder="请输入学生姓名"
  45. :filter-method="filterStudent"
  46. v-model="seleched"
  47. :render-content="renderFunc"
  48. :data="data"
  49. :class="{hideReturn: !canDelUser}"
  50. >
  51. <template #left-footer>
  52. <div class="footer line">
  53. <span>姓名</span>
  54. <span>性别</span>
  55. <span>专业</span>
  56. </div>
  57. </template>
  58. <template #right-footer>
  59. <div class="footer line">
  60. <span>姓名</span>
  61. <span>性别</span>
  62. <span>专业</span>
  63. </div>
  64. </template>
  65. </el-transfer>
  66. </el-form>
  67. <div slot="footer" class="dialog-footer">
  68. <el-button @click="$listeners.close">取 消</el-button>
  69. <el-button type="primary" @click="submit">确 定</el-button>
  70. </div>
  71. </div>
  72. </template>
  73. <script>
  74. import { genderType } from "@/constant";
  75. import { updateClassGroupStudents } from '../../api'
  76. import { uniqBy } from 'lodash'
  77. export default {
  78. props: ["studentList", "soundList", "activeType", 'activeListStudent', 'isOnlyChangeUser', 'classGroupId', 'type'],
  79. computed: {
  80. data() {
  81. return uniqBy([...this.studentList, ...this.activeListStudent], 'userId')
  82. .filter(item => {
  83. if (this.sound.length) {
  84. return this.sound.includes(item.subjectId) || this.seleched.includes(item.userId)
  85. }
  86. return true
  87. })
  88. .map((item) => ({
  89. value: item.userId,
  90. key: item.userId,
  91. name: item.name,
  92. subjectName: item.subjectName,
  93. gender: genderType[item.gender],
  94. }));
  95. },
  96. showName() {
  97. return !this.isOnlyChangeUser && this.activeType != 'MUSIC_NETWORK'
  98. },
  99. canDelUser() {
  100. return this.$route.query.type !== 'resetTeam' || !this.isOnlyChangeUser
  101. }
  102. },
  103. data() {
  104. return {
  105. sound: [],
  106. form: {
  107. name: '',
  108. },
  109. seleched: [],
  110. };
  111. },
  112. watch: {
  113. activeListStudent() {
  114. this.setSelectedUser()
  115. },
  116. },
  117. mounted() {
  118. this.setSelectedUser()
  119. },
  120. methods: {
  121. setSelectedUser() {
  122. const ids = this.activeListStudent.map(item => item.userId)
  123. this.seleched = [...ids]
  124. },
  125. filterStudent(query, item) {
  126. return (
  127. item.name.indexOf(query) > -1 ||
  128. item.subjectName.indexOf(query) > -1 ||
  129. item.gender.indexOf(query) > -1
  130. );
  131. },
  132. renderFunc(h, option) {
  133. return (
  134. <div class="line">
  135. <span>{option.name}</span>
  136. <span>{option.gender}</span>
  137. <span>{option.subjectName}</span>
  138. </div>
  139. );
  140. },
  141. change(val) {
  142. this.$listeners.changeActiveChioseSound(val)
  143. this.$listeners.searchStudent()
  144. },
  145. submit() {
  146. if (!this.isOnlyChangeUser && this.activeType == 'HIGH_ONLINE' && (this.seleched.length < 3 || this.seleched.length > 5)) {
  147. return this.$message.error('线上技能班必须为3-5人')
  148. }
  149. if (this.seleched.length < 1) {
  150. return this.$message.error('请至少选择一名学生')
  151. }
  152. if (this.activeType == 'MUSIC_NETWORK' && this.seleched.length > 1) {
  153. return this.$message.error('乐团网管课仅可添加一名学生')
  154. }
  155. this.$refs.form.validate(async valid => {
  156. if (valid) {
  157. if (this.isOnlyChangeUser && this.type !== 'change') {
  158. try {
  159. await updateClassGroupStudents({
  160. classGroupId: this.classGroupId,
  161. studentIds: this.seleched.join(',')
  162. })
  163. this.$message.success('提交成功')
  164. } catch (error) {}
  165. this.$listeners.submited()
  166. } else {
  167. this.$listeners.submited({
  168. seleched: this.seleched,
  169. name: this.form.name
  170. })
  171. }
  172. this.$listeners.close()
  173. }
  174. })
  175. }
  176. },
  177. };
  178. </script>
  179. <style lang="less" scoped>
  180. /deep/ .el-transfer {
  181. display: flex;
  182. align-items: center;
  183. .el-transfer__buttons {
  184. display: flex;
  185. width: 110px;
  186. flex-direction: column;
  187. > button {
  188. &:last-child {
  189. margin-left: 0;
  190. }
  191. }
  192. }
  193. .el-transfer-panel {
  194. width: 300px;
  195. }
  196. }
  197. .footer {
  198. margin-left: 35px;
  199. margin-right: auto;
  200. height: 40px;
  201. line-height: 40px;
  202. }
  203. .hideReturn{
  204. /deep/ .el-transfer__buttons button:first-child{
  205. display: none;
  206. }
  207. }
  208. /deep/ .el-checkbox-group{
  209. padding-bottom: 40px;
  210. }
  211. /deep/ .line {
  212. width: 220px;
  213. display: flex;
  214. justify-content: space-around;
  215. }
  216. /deep/ .dialog-footer{
  217. margin-top: 20px;
  218. display: block;
  219. text-align: right;
  220. }
  221. </style>