addUser.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. <template>
  2. <el-dialog v-model="showDialog" :title="dialogData.pageType == 'add' ? '新增用户' : dialogData.pageType == 'edit' ? '编辑用户' : ''" width="600px">
  3. <el-form :model="userForm" :rules="rules" ref="userFormRef">
  4. <el-form-item label="学校名称:" :label-width="formLabelWidth" prop="tenantName">
  5. <el-input v-model="userForm.tenantName" placeholder="请输入学校名称" />
  6. </el-form-item>
  7. <el-form-item label="学校简称:" :label-width="formLabelWidth" prop="abbreviation">
  8. <el-input v-model="userForm.abbreviation" placeholder="请输入学校名称" />
  9. </el-form-item>
  10. <el-form-item label="区域:" :label-width="formLabelWidth" required>
  11. <el-form-item prop="provinceCode">
  12. <el-select v-model="userForm.provinceCode" placeholder="请选择" @change="handleProvinceChange" style="width: 100px;">
  13. <el-option
  14. v-for="province in provinceTreeList || []"
  15. :key="province.provinceCode"
  16. :label="province.provinceName"
  17. :value="province.provinceCode"
  18. ></el-option>
  19. </el-select>
  20. <span class="margin_10">省</span>
  21. </el-form-item>
  22. <el-form-item prop="cityCode">
  23. <el-select v-model="userForm.cityCode" placeholder="请选择" @change="handleCityChange" style="width: 100px;">
  24. <el-option
  25. v-for="city in cityTreeList || []"
  26. :key="city.cityCode"
  27. :label="city.cityName"
  28. :value="city.cityCode"
  29. ></el-option>
  30. </el-select>
  31. <span class="margin_10">市</span>
  32. </el-form-item>
  33. <el-form-item prop="areaCode">
  34. <el-select v-model="userForm.areaCode" placeholder="请选择" @change="handleAreaChange" style="width: 100px;">
  35. <el-option
  36. v-for="district in areaList || []"
  37. :key="district.districtCode"
  38. :label="district.districtName"
  39. :value="district.districtCode"
  40. ></el-option>
  41. </el-select>
  42. <span class="margin_10">区/县</span>
  43. </el-form-item>
  44. </el-form-item>
  45. <el-form-item label="账号类型:" :label-width="formLabelWidth" prop="schoolType">
  46. <el-radio-group v-model="userForm.schoolType">
  47. <el-radio :value="0">单校版</el-radio>
  48. <el-radio :value="1">联考版</el-radio>
  49. </el-radio-group>
  50. </el-form-item>
  51. <el-form-item label="用户类型:" :label-width="formLabelWidth" prop="type">
  52. <el-radio-group v-model="userForm.type">
  53. <el-radio :value="1">正式用户</el-radio>
  54. <el-radio :value="0">体验用户</el-radio>
  55. </el-radio-group>
  56. </el-form-item>
  57. <el-form-item label="学校logo:" :label-width="formLabelWidth">
  58. <img v-if="userForm.image" :src="userForm.image" alt="" class="file_image">
  59. <img v-else src="@/assets/school/default_logo.svg" alt="" class="file_image">
  60. <el-upload :http-request="UploadLogo">
  61. <el-button size="small" type="primary">{{ userForm.image ? '重新上传' : '上传logo'}}</el-button>
  62. </el-upload>
  63. </el-form-item>
  64. <el-form-item label="有效时间:" :label-width="formLabelWidth" required>
  65. <el-form-item prop="startDate">
  66. <el-date-picker
  67. v-model="userForm.startDate"
  68. type="date"
  69. placeholder="请选择"
  70. format="YYYY/MM/DD"
  71. value-format="YYYY-MM-DD"
  72. /><span class="margin_10">至</span>
  73. </el-form-item>
  74. <el-form-item prop="endDate">
  75. <el-date-picker
  76. v-model="userForm.endDate"
  77. type="date"
  78. placeholder="请选择"
  79. format="YYYY/MM/DD"
  80. value-format="YYYY-MM-DD"
  81. />
  82. </el-form-item>
  83. </el-form-item>
  84. <el-form-item label="运维负责人:" :label-width="formLabelWidth" prop="sysUserId">
  85. <el-select v-model="userForm.sysUserId" placeholder="请选择" @change="handleUserChange" style="width: 320px;" multiple collapse-tags collapse-tags-tooltip>
  86. <el-option
  87. v-for="item in userList"
  88. :key="item.id"
  89. :label="item.nickname"
  90. :value="item.id"
  91. ></el-option>
  92. </el-select>
  93. </el-form-item>
  94. </el-form>
  95. <template #footer>
  96. <el-button class="button_border_gray cancel" @click="showDialog = false">取消</el-button>
  97. <el-button class="button_background" :loading="submitLoading" @click="SubmitForm(userFormRef)">确定</el-button>
  98. </template>
  99. </el-dialog>
  100. </template>
  101. <script lang="ts">
  102. export default {
  103. name: 'AddUser',
  104. }
  105. </script>
  106. <script lang="ts" setup>
  107. import { ref, reactive, inject, onMounted } from 'vue'
  108. import type { FormInstance, FormRules } from 'element-plus'
  109. import { ElMessage } from 'element-plus'
  110. import { getUserList, addUser, uploadFile, provinceTree, getSchoolInfo, editSchoolInfo } from '@/api/school'
  111. interface DialogData {
  112. pageType: string
  113. id: string
  114. }
  115. let showDialog = inject('showDialog')
  116. let dialogData = inject<DialogData>('dialogData', {
  117. pageType: 'add',
  118. id: ''
  119. })
  120. const formLabelWidth = '120px'
  121. // 新增用户表单数据定义
  122. interface UserForm {
  123. id: string
  124. tenantName: string
  125. abbreviation: string
  126. provinceCode: string
  127. provinceName: string
  128. cityCode: string
  129. cityName: string
  130. areaCode: string
  131. areaName: string
  132. schoolType: number
  133. type: number
  134. image: string
  135. startDate: string
  136. endDate: string
  137. // selUserList: string[]
  138. sysUserId: string[]
  139. }
  140. // 新增用户表单数据初始化
  141. const userForm = reactive<UserForm>({
  142. id: '',
  143. tenantName: '',
  144. abbreviation: '',
  145. provinceCode: '',
  146. provinceName: '',
  147. cityCode: '',
  148. cityName: '',
  149. areaCode: '',
  150. areaName: '',
  151. schoolType: 0,
  152. type: 1,
  153. image: '',
  154. startDate: '',
  155. endDate: '',
  156. // selUserList: [],
  157. sysUserId: []
  158. })
  159. const userFormRef = ref<FormInstance>()
  160. // 表单校验规则
  161. const rules = reactive<FormRules<UserForm>>({
  162. tenantName: [
  163. { required: true, message: '请输入学校名称', trigger: 'blur' }
  164. ],
  165. // abbreviation: [
  166. // { required: true, message: '请输入学校简称', trigger: 'blur' }
  167. // ],
  168. provinceCode: [
  169. { required: true, message: '请选择省', trigger: 'change' }
  170. ],
  171. cityCode: [
  172. { required: true, message: '请选择市', trigger: 'change' }
  173. ],
  174. areaCode: [
  175. { required: true, message: '请选择区/县', trigger: 'change' }
  176. ],
  177. schoolType: [
  178. { required: true, message: '请选择账号类型', trigger: 'change' }
  179. ],
  180. type: [
  181. { required: true, message: '请选择用户类型', trigger: 'change' }
  182. ],
  183. startDate: [
  184. { required: true, message: '请选择开始时间', trigger: 'change' }
  185. ],
  186. endDate: [
  187. { required: true, message: '请选择结束时间', trigger: 'change' }
  188. ],
  189. // sysUserId: [
  190. // { required: true, message: '请选择运维人员', trigger: 'change' }
  191. // ]
  192. })
  193. interface Province {
  194. provinceCode: string
  195. provinceName: string
  196. children?: City[] // 可选字段
  197. }
  198. interface City {
  199. cityCode: string
  200. cityName: string
  201. children?: District[]
  202. }
  203. interface District {
  204. districtCode: string
  205. districtName: string
  206. }
  207. // 省份列表
  208. const provinceTreeList = ref<Province[]>([])
  209. // 市列表
  210. const cityTreeList = ref<City[]>([])
  211. // 区/县列表
  212. const areaList = ref<District[]>([])
  213. interface User {
  214. id: string
  215. nickname: string
  216. }
  217. // 运维人员列表
  218. const userList = ref<User[]>([])
  219. // 提交按钮loading
  220. const submitLoading = ref(false)
  221. onMounted (async () => {
  222. await GetProvinceTree()
  223. await GetUserList()
  224. if(dialogData.pageType == 'edit') {
  225. await GetUserDetail()
  226. }
  227. })
  228. // 获取用户详情
  229. const GetUserDetail = () => {
  230. getSchoolInfo(dialogData.id).then((res: any) => {
  231. if(res.code == 200 && res.data) {
  232. const { data } = res
  233. if(data.provinceCode) {
  234. cityTreeList.value = provinceTreeList.value.find(item => item.provinceCode == data.provinceCode).children
  235. }
  236. if(data.cityCode) {
  237. areaList.value = cityTreeList.value.find(item => item.cityCode == data.cityCode).children
  238. }
  239. userForm.id = data.id
  240. userForm.tenantName = data.tenantName
  241. userForm.abbreviation = data.abbreviation
  242. userForm.provinceCode = data.provinceCode
  243. userForm.provinceName = data.provinceName
  244. userForm.cityCode = data.cityCode
  245. userForm.cityName = data.cityName
  246. userForm.areaCode = data.areaCode
  247. userForm.areaName = data.areaName
  248. userForm.schoolType = data.schoolType
  249. userForm.type = data.type
  250. userForm.image = data.image
  251. userForm.startDate = data.startDate
  252. userForm.endDate = data.endDate
  253. // userForm.selUserList = data.selUserList
  254. userForm.sysUserId = data.sysUserId
  255. }
  256. })
  257. }
  258. // 获取运维人员列表
  259. const GetUserList = () => {
  260. getUserList({}).then((res: any) => {
  261. if(res.code == 200 && res.data) {
  262. const { data } = res
  263. userList.value = data
  264. }
  265. })
  266. }
  267. // 获取省市区树列表
  268. const GetProvinceTree = (): Promise<void> => {
  269. return new Promise((resolve) => {
  270. provinceTree().then((res: any) => {
  271. if(res.code == 200 && res.data) {
  272. const { data } = res
  273. provinceTreeList.value = data
  274. resolve()
  275. }
  276. })
  277. })
  278. }
  279. // 选择省份
  280. const handleProvinceChange = (val: any) => {
  281. userForm.provinceCode = val
  282. userForm.provinceName = provinceTreeList.value.find(item => item.provinceCode == val)?.provinceName
  283. cityTreeList.value = provinceTreeList.value.find(item => item.provinceCode == val)?.children
  284. areaList.value = []
  285. userForm.cityCode = ''
  286. userForm.areaCode = ''
  287. }
  288. // 选择市
  289. const handleCityChange = (val: any) => {
  290. userForm.cityCode = val
  291. userForm.cityName = cityTreeList.value.find(item => item.cityCode == val)?.cityName
  292. areaList.value = cityTreeList.value.find(item => item.cityCode == val)?.children
  293. userForm.areaCode = ''
  294. }
  295. // 选择区/县
  296. const handleAreaChange = (val: any) => {
  297. userForm.areaCode = val
  298. userForm.areaName = areaList.value.find(item => item.districtCode == val)?.districtName
  299. }
  300. // 上传学校logo
  301. const UploadLogo = (file: any) => {
  302. let formData = new FormData();
  303. formData.append("file", file.file);
  304. uploadFile(formData).then((res: any) => {
  305. console.log(res)
  306. if(res.code == 200 && res.data) {
  307. const { data } = res
  308. userForm.image = data.url
  309. }
  310. })
  311. }
  312. // 选择运维人员
  313. const handleUserChange = (val: any) => {
  314. console.log(val)
  315. let result = userList.value.filter(item => val.includes(item.id)).map(item => {
  316. return { id: item.id }
  317. })
  318. console.log(result)
  319. // userForm.selUserList = val
  320. userForm.sysUserId = val
  321. }
  322. const emit = defineEmits(['AddUser'])
  323. // 表单提交
  324. const SubmitForm = async (formEl: FormInstance | undefined) => {
  325. if (!formEl) return
  326. await formEl.validate(async(valid) => {
  327. if (valid) {
  328. submitLoading.value = true
  329. try {
  330. let res
  331. if(dialogData.pageType == 'add') {
  332. res = await addUser(userForm)
  333. }else if(dialogData.pageType == 'edit') {
  334. res = await editSchoolInfo(userForm)
  335. }
  336. if (res.code == 200) {
  337. ElMessage.success(res.msg)
  338. if(userFormRef.value) {
  339. userFormRef.value.resetFields()
  340. }
  341. emit('AddUser', false)
  342. } else {
  343. ElMessage.error(res.msg)
  344. }
  345. submitLoading.value = false
  346. }catch {
  347. submitLoading.value = false
  348. }
  349. }
  350. })
  351. }
  352. </script>
  353. <style lang="scss" scoped>
  354. .file_image {
  355. width: 48px;
  356. height: 48px;
  357. margin-right: 10px;
  358. border-radius: 50%;
  359. }
  360. .margin_10 {
  361. margin: 0 10px;
  362. }
  363. .el-input {
  364. width: 320px;
  365. }
  366. .el-upload .el-button {
  367. width: 76px;
  368. height: 32px;
  369. background: #2E64FA1A;
  370. color: #2E64FA;
  371. border: none;
  372. }
  373. </style>