addEdit.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. <script setup lang="ts">
  2. import { httpAdd, httpUpdate } from "/@/api/interest/companyAccount";
  3. import { ElMessage, FormInstance, FormRules } from "element-plus";
  4. import { reactive, ref, watch, nextTick } from "vue";
  5. import { useNav } from "/@/layout/hooks/nav";
  6. import { isMobile } from "/@/utils/validate";
  7. import CompanyModal from "./components/company-modal.vue";
  8. import { type menuType } from "./types";
  9. import { useUserInfo } from "/@/hooks/core/useUser";
  10. const { logout } = useNav();
  11. const formSize = ref("default");
  12. const ruleFormRef = ref<FormInstance>();
  13. const props = defineProps({
  14. itemId: {
  15. type: String,
  16. default: ""
  17. },
  18. showModel: {
  19. type: Boolean,
  20. default: false
  21. },
  22. isDetails: {
  23. type: String,
  24. default: "add"
  25. },
  26. sitem: {
  27. type: Object as PropType<menuType>
  28. }
  29. });
  30. const defaultCompany = ref<boolean[]>([]);
  31. let defaultCompanyNo = "";
  32. const showModelThis = ref(false);
  33. const emit = defineEmits<{
  34. (e: "cancel"): void;
  35. (e: "refresh"): void;
  36. }>();
  37. const id = ref("");
  38. const editType = ref("add");
  39. const formModel = {
  40. id: "", //账户id
  41. nickname: "", //真实姓名
  42. mobile: "", //手机号
  43. companyArr: []
  44. };
  45. const tableRef = ref<any>(null);
  46. const ruleForm = reactive<menuType>({ ...formModel });
  47. const companyModalRef = ref<InstanceType<typeof CompanyModal> | null>(null);
  48. const { isSuperUser } = useUserInfo();
  49. let originCompanyArr: any[] = [];
  50. const rules = reactive<FormRules>({
  51. nickname: [
  52. { required: true, message: "请输入真实姓名", trigger: "blur" },
  53. { min: 2, max: 12, message: "长度在 2 到 12 个字符", trigger: "blur" }
  54. ],
  55. mobile: [
  56. {
  57. required: true,
  58. validator: (rule, value, callback) => {
  59. if (value === "") {
  60. callback(new Error("手机号不能为空!"));
  61. } else if (!isMobile(value)) {
  62. callback(new Error("手机号格式不正确!"));
  63. } else {
  64. callback();
  65. }
  66. },
  67. trigger: "blur"
  68. }
  69. ],
  70. companyArr: [
  71. {
  72. required: true,
  73. validator: (rule, value, callback) => {
  74. if (value.length === 0) {
  75. callback(new Error("请选择业务公司"));
  76. } else {
  77. callback();
  78. }
  79. }
  80. }
  81. ]
  82. });
  83. const submitForm = async (formEl: FormInstance | undefined) => {
  84. if (!formEl) return;
  85. if (!defaultCompanyNo) {
  86. ElMessage.warning("请选择默认公司");
  87. return;
  88. }
  89. await formEl.validate(async (valid, fields) => {
  90. if (valid) {
  91. if (loading.value === true) return;
  92. const model = Object.assign({}, ruleForm);
  93. if (editType.value === "add") delete model.id;
  94. const current = model.companyArr.map(({ companyCode }) => companyCode);
  95. const dels = originCompanyArr
  96. .filter(({ companyCode }) => !current.includes(companyCode))
  97. .map(({ companyCode, companyName, id }) => ({
  98. id,
  99. companyCode,
  100. companyName,
  101. is_del: 1,
  102. is_main: "0"
  103. }));
  104. const orgs = originCompanyArr
  105. .filter(({ companyCode }) => current.includes(companyCode))
  106. .map(({ companyCode, companyName, id }) => ({
  107. id,
  108. companyCode,
  109. companyName,
  110. is_del: 0,
  111. is_main: "0"
  112. }));
  113. const adds = model.companyArr
  114. .filter(({ companyCode: code }) => {
  115. return (
  116. !dels.find(({ companyCode }) => companyCode === code) &&
  117. !orgs.find(({ companyCode }) => companyCode === code)
  118. );
  119. })
  120. .map(({ companyCode, companyName, id }) => ({
  121. id,
  122. companyCode,
  123. companyName,
  124. is_main: "0",
  125. is_del: 0
  126. }));
  127. model.companyArr = [...dels, ...orgs, ...adds];
  128. model.companyArr.forEach(item => {
  129. if (item.companyCode === defaultCompanyNo) {
  130. item.is_main = "1";
  131. }
  132. });
  133. loading.value = true;
  134. const { code, message } =
  135. editType.value === "add"
  136. ? await httpAdd(model)
  137. : await httpUpdate(model);
  138. loading.value = false;
  139. if (code === 0) {
  140. ElMessage.success(titleType.value + "成功!");
  141. showModelThis.value = false;
  142. emit("refresh");
  143. } else if (code > 100 && code < 140) {
  144. showModelThis.value = false;
  145. logout();
  146. } else {
  147. ElMessage.error(message);
  148. }
  149. } else {
  150. console.log("error submit!", fields);
  151. }
  152. });
  153. };
  154. const resetForm = async (formEl: FormInstance | undefined, item) => {
  155. if (formEl) {
  156. formEl.clearValidate();
  157. formEl.resetFields();
  158. }
  159. await nextTick(async () => {
  160. for (let key in ruleForm) {
  161. if (key === "companyArr" && item["company_relaton"]) {
  162. if (editType.value !== "add") {
  163. item["company_relaton"].forEach(item => {
  164. ruleForm.companyArr.push({ ...item });
  165. });
  166. } else {
  167. ruleForm.companyArr = [];
  168. }
  169. } else {
  170. ruleForm[key] = item[key];
  171. }
  172. }
  173. });
  174. originCompanyArr = item.company_relaton?.map(item => ({ ...item })) || [];
  175. if (editType.value === "add") {
  176. ruleForm.companyArr = [];
  177. originCompanyArr = [];
  178. }
  179. };
  180. const closeDialog = () => {
  181. showModelThis.value = false;
  182. defaultCompany.value = [];
  183. ruleForm.companyArr = [];
  184. defaultCompanyNo = "";
  185. emit("cancel");
  186. };
  187. const loading = ref(true);
  188. const titleType = ref("");
  189. async function initForm(item: Object) {
  190. loading.value = true;
  191. switch (editType.value) {
  192. case "add":
  193. titleType.value = "新建账号";
  194. break;
  195. case "edit":
  196. titleType.value = "编辑账号";
  197. break;
  198. case "view":
  199. titleType.value = "账号详情";
  200. break;
  201. default:
  202. titleType.value = "新建账号";
  203. }
  204. resetForm(ruleFormRef.value, item);
  205. loading.value = false;
  206. }
  207. function handleDelete(index) {
  208. ruleForm.companyArr.splice(index, 1);
  209. if (defaultCompany.value[index]) {
  210. defaultCompanyNo = "";
  211. }
  212. defaultCompany.value.splice(index, 1);
  213. if (ruleForm.companyArr.length >= 1) {
  214. defaultCompany.value[index] = true;
  215. const current = ruleForm.companyArr[index];
  216. if (current) {
  217. defaultCompanyNo = ruleForm.companyArr[index].companyCode;
  218. defaultCompany.value[index] = true;
  219. return;
  220. }
  221. defaultCompanyNo = ruleForm.companyArr[index - 1].companyCode;
  222. defaultCompany.value[index - 1] = true;
  223. }
  224. }
  225. function handleChoose(companys) {
  226. const codes = ruleForm.companyArr.map(({ companyCode }) => companyCode);
  227. companys.forEach(item => {
  228. if (!codes.includes(item.companyNo)) {
  229. const { companyNo, company_name } = item;
  230. ruleForm.companyArr.push({
  231. companyCode: companyNo,
  232. companyName: company_name
  233. });
  234. }
  235. });
  236. defaultCompany.value = ruleForm.companyArr.map(() => false);
  237. const index = ruleForm.companyArr.findIndex(
  238. ({ companyCode }) => companyCode === defaultCompanyNo
  239. );
  240. if (index >= 0) {
  241. defaultCompany.value[index] = true;
  242. }
  243. }
  244. watch(
  245. () => {
  246. return props.showModel;
  247. },
  248. () => {
  249. const { showModel, itemId, isDetails, sitem } = props as any;
  250. showModelThis.value = showModel;
  251. if (showModelThis.value) {
  252. id.value = itemId;
  253. editType.value = isDetails;
  254. if (isDetails !== "add") {
  255. initForm(sitem);
  256. } else {
  257. initForm(formModel);
  258. }
  259. }
  260. if (editType.value === "edit" || editType.value === "view") {
  261. const index = sitem.company_relaton.findIndex(
  262. ({ is_main }) => String(is_main) === "1"
  263. );
  264. if (index >= 0) {
  265. defaultCompany.value = sitem.company_relaton.map(() => false);
  266. defaultCompanyNo = sitem.company_relaton[index].companyCode;
  267. defaultCompany.value[index] = true;
  268. }
  269. }
  270. }
  271. );
  272. function handleDefaultCompanyChange(index: number) {
  273. defaultCompany.value.forEach((_, index) => {
  274. defaultCompany.value[index] = false;
  275. });
  276. defaultCompanyNo = ruleForm.companyArr[index].companyCode;
  277. defaultCompany.value[index] = true;
  278. }
  279. </script>
  280. <template>
  281. <el-dialog
  282. :close-on-press-escape="false"
  283. v-model="showModelThis"
  284. append-to-body
  285. :width="'900px'"
  286. center
  287. :title="titleType"
  288. v-loading="loading"
  289. @close="closeDialog"
  290. >
  291. <el-form
  292. class="demo-ruleForm"
  293. ref="ruleFormRef"
  294. :model="ruleForm"
  295. :rules="rules"
  296. label-width="90px"
  297. :size="formSize"
  298. status-icon
  299. >
  300. <el-row>
  301. <el-col :span="24">
  302. <el-form-item label="真实姓名" prop="nickname">
  303. <el-input
  304. v-model="ruleForm.nickname"
  305. :disabled="editType === 'view'"
  306. placeholder="真实姓名"
  307. /> </el-form-item
  308. ></el-col>
  309. <el-col :span="24">
  310. <el-form-item label="手机号" prop="mobile">
  311. <el-input
  312. v-model="ruleForm.mobile"
  313. :disabled="editType === 'view'"
  314. :maxlength="11"
  315. placeholder="手机号"
  316. /> </el-form-item
  317. ></el-col>
  318. <el-col :span="24">
  319. <el-form-item label="业务公司" prop="companyArr">
  320. <el-table
  321. :data="ruleForm.companyArr"
  322. border
  323. size="small"
  324. row-key="companyCode"
  325. reserve-selection
  326. ref="tableRef"
  327. >
  328. <el-table-column label="默认公司" width="80px">
  329. <template #="{ $index }">
  330. <div class="w-full flex justify-center">
  331. <el-checkbox
  332. :disabled="editType === 'view'"
  333. v-model="defaultCompany[$index]"
  334. @change="() => handleDefaultCompanyChange($index)"
  335. />
  336. </div>
  337. </template>
  338. </el-table-column>
  339. <el-table-column label="公司编号" prop="companyCode" />
  340. <el-table-column label="公司名称" prop="companyName" />
  341. <el-table-column
  342. v-if="editType !== 'view' && isSuperUser"
  343. width="100px"
  344. label="操作"
  345. >
  346. <template #header>
  347. <div class="w-full flex justify-between items-center">
  348. <div>操作</div>
  349. <ElButton
  350. text
  351. type="primary"
  352. @click="() => companyModalRef.onDisplay()"
  353. >添加</ElButton
  354. >
  355. </div>
  356. </template>
  357. <template #="{ $index }">
  358. <ElButton
  359. text
  360. type="danger"
  361. @click="() => handleDelete($index)"
  362. >删除</ElButton
  363. >
  364. </template>
  365. </el-table-column>
  366. </el-table>
  367. </el-form-item></el-col
  368. >
  369. </el-row>
  370. <el-col :span="24" class="clear">
  371. <el-button
  372. v-if="editType === 'add' || editType === 'edit'"
  373. type="primary"
  374. class="fr"
  375. style="margin: 0 0 0 16px"
  376. @click="submitForm(ruleFormRef)"
  377. :loading="loading"
  378. >保存</el-button
  379. >
  380. <el-button class="fr" style="margin: 0 0 0 16px" @click="closeDialog"
  381. >关闭</el-button
  382. >
  383. </el-col>
  384. </el-form>
  385. <CompanyModal ref="companyModalRef" @choose="handleChoose" />
  386. </el-dialog>
  387. </template>