organization-add.vue 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <template>
  2. <!-- "ancestors": "",
  3. "contact": "",
  4. "orderNum": 0,
  5. "orgId": 0,
  6. "orgName": "",
  7. "parentId": 0,
  8. "password": "",
  9. "type": 0,
  10. "userName": "" -->
  11. <el-form label-width="100px" :model="data" :rules="rules" ref="baseFormRef">
  12. <el-form-item label="单位名称" prop="orgName" required>
  13. <el-input v-model.trim="data.orgName" style="width: 300px" :maxlength="50" placeholder="请输入" />
  14. </el-form-item>
  15. <el-form-item label="类型" prop="type" required>
  16. <!-- <el-input v-model="data.type" style="width: 300px" :maxlength="500" placeholder="请输入" /> -->
  17. <el-select style="width: 300px" v-model="data.type">
  18. <el-option :value="Number(key)" :label="type" v-for="(type, key) in OrganizationTypeDesc" />
  19. </el-select>
  20. </el-form-item>
  21. <el-form-item label="行政区划">
  22. <el-cascader style="width: 300px" v-model="selectedValue" :props="lazyProps" :placeholder="'请选择地区'" clearable
  23. @change="handleChange" lazy />
  24. </el-form-item>
  25. <el-form-item label="上级单位" prop="parentId">
  26. <el-tree-select :check-strictly="true" :props="{
  27. value: 'orgId',
  28. label: (data: any) => data.orgName,
  29. }" style="width: 300px" v-model="data.parentId" :data="allOrgs" node-key="orgId" clearable>
  30. </el-tree-select>
  31. </el-form-item>
  32. <el-form-item label="联系人" prop="contact" required>
  33. <el-input v-model.trim="data.contact" style="width: 300px" :maxlength="50" placeholder="请输入" />
  34. </el-form-item>
  35. <el-form-item label="账号" prop="userName" required>
  36. <el-input v-model.trim="data.userName" style="width: 300px" :maxlength="11" placeholder="请输入手机号" />
  37. </el-form-item>
  38. <el-form-item label="密码" prop="password" required>
  39. <el-input autocomplete="off" readonly onfocus="this.removeAttribute('readonly');" v-model.trim="data.password"
  40. :type="addPassFlag ? 'text' : 'password'" style="width: 300px" :maxlength="500"
  41. placeholder="请输入8-16位数字、字母大小写组合">
  42. <template #suffix>
  43. <span @click="addPassFlag = !addPassFlag" style="cursor: pointer">
  44. <el-icon v-if="addPassFlag">
  45. <View />
  46. </el-icon>
  47. <el-icon v-else>
  48. <Hide />
  49. </el-icon>
  50. </span>
  51. </template>
  52. </el-input>
  53. </el-form-item>
  54. </el-form>
  55. </template>
  56. <script setup lang="ts">
  57. import { QuiskExpose } from "@/helper/mount";
  58. import type { FormInstance, FormRules } from "element-plus";
  59. // import { ElMessage } from "element-plus";
  60. import type { OrganizationType } from "@/request/organization";
  61. import { OrganizationTypeDesc } from "@/store/organization";
  62. import { globalPasswordRex } from "@/util/regex";
  63. import { ref, reactive, unref, watch, onMounted } from "vue";
  64. import { getProvinces, getCities, getAreas } from '@/request/organization';
  65. import { View, Hide } from "@element-plus/icons-vue";
  66. // import { user } from '@/store/user'
  67. import { getOrgListFetchList } from "@/request";
  68. import type { CascaderProps, CascaderOption } from 'element-plus'
  69. const addPassFlag = ref(true); //图标显示标识
  70. const selectedValue = ref([])
  71. type SelectType = {
  72. orgName: string;
  73. orgId: number;
  74. children: SelectType[];
  75. };
  76. const baseFormRef = ref<FormInstance>();
  77. const allOrgs = ref<SelectType[]>([]);
  78. const rules = reactive<FormRules>({
  79. orgName: [{ required: true, message: "请输入单位名称", trigger: "blur" }],
  80. type: [{ required: true, message: "请选择类型", trigger: "change" }],
  81. contact: [{ required: true, message: "请输入联系人", trigger: "blur" }],
  82. userName: [
  83. {
  84. required: true,
  85. pattern: /^1[3456789]\d{9}$/,
  86. message: "请输入正确手机号",
  87. trigger: "blur",
  88. },
  89. ],
  90. password: [
  91. {
  92. required: true,
  93. pattern: globalPasswordRex,
  94. message: "请输入8-16位数字、字母大小写组合",
  95. trigger: "blur",
  96. },
  97. { required: true, min: 8, message: "密码太短!", trigger: "blur" },
  98. ],
  99. });
  100. const props = defineProps<{
  101. submit: (data: OrganizationType) => Promise<any>;
  102. }>();
  103. const data = ref<OrganizationType & {}>({
  104. ancestors: "",
  105. contact: "",
  106. orderNum: 0,
  107. orgId: 0,
  108. orgName: "",
  109. parentId: null,
  110. password: "",
  111. type: null,
  112. userName: "",
  113. });
  114. // const setParentId = () => {
  115. // if (user.value) {
  116. // const isSuper = user.value.roles.filter(item => item.roleKey === "super_admin").length > 0;
  117. // data.value.parentId = isSuper ? 0 : Number(data.value.parentId)
  118. // }
  119. // }
  120. onMounted(async () => {
  121. const data = await getOrgListFetchList();
  122. // console.log('allOrgs', data);
  123. allOrgs.value = data as any as SelectType[];
  124. debugger
  125. });
  126. watch(
  127. data,
  128. (newValue) => {
  129. data.value.userName = newValue.userName.replace(/[^0-9]/g, "");
  130. },
  131. {
  132. immediate: true,
  133. deep: true,
  134. }
  135. );
  136. // 动态加载配置
  137. const lazyProps = ref<CascaderProps>({
  138. lazy: true,
  139. // 启用懒加载模式
  140. async lazyLoad(node, resolve) {
  141. // debugger
  142. const { level, value } = node; // level: 当前层级(0=省,1=市,2=区)
  143. console.log('node', node.data)
  144. const dataRes = await loadData(level, node.data);
  145. resolve(dataRes); // 将子节点数据返回给组件
  146. },
  147. checkStrictly: true, // 允许选择任意一级(可选)
  148. label: 'name', // 显示字段名
  149. value: 'id', // 值字段名
  150. leaf: 'leaf', // 标识是否为叶子节点(不可再展开)
  151. });
  152. const loadData = async (level, node) => {
  153. // 根据层级模拟数据
  154. console.log('level', level, node)
  155. switch (level) {
  156. case 0: // 加载省份
  157. const provinces = await getProvinces();
  158. const resP = Array.from(provinces as any as CascaderProps[]).map(p => {
  159. return p
  160. });
  161. return resP;
  162. case 1:
  163. let cities
  164. if (node.zx) {
  165. const areas = await getAreas(node.province, node.city);
  166. console.log('areas', areas)
  167. cities = Array.from(areas as any as CascaderOption[]).map(a => {
  168. a.leaf = true
  169. return a
  170. })
  171. } else {
  172. cities = await getCities(node.province);
  173. console.log('cities', node.province, cities);
  174. }
  175. return cities
  176. // break;
  177. case 2: // 加载区县
  178. const areas = await getAreas(node.province, node.city)
  179. console.log('areas', areas)
  180. return Array.from(areas as any as CascaderOption[]).map(a => {
  181. a.leaf = true
  182. return a
  183. })
  184. default:
  185. return [];
  186. }
  187. };
  188. // 处理选择事件
  189. const handleChange = (value: string) => {
  190. console.log('选中的省市区编码:', value);
  191. };
  192. defineExpose<QuiskExpose>({
  193. async submit() {
  194. if (unref(baseFormRef)) {
  195. // setParentId();
  196. const res = await unref(baseFormRef)?.validate();
  197. if (res) {
  198. console.log("data", data.value);
  199. if (selectedValue.value.length > 0) {
  200. data.value.provinceId = selectedValue.value[0]
  201. data.value.cityId = selectedValue.value[1]
  202. data.value.areaId = selectedValue.value[2]
  203. }
  204. await props.submit(data.value as any as OrganizationType);
  205. }
  206. } else {
  207. throw "";
  208. }
  209. },
  210. });
  211. </script>