insuranceCompanyConfig.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. <!-- 模板区域 -->
  2. <template>
  3. <div>
  4. <PageMain class="vh100">
  5. <el-form :inline="true" :model="formInline" class="demo-form-inline">
  6. <el-form-item label="保险公司">
  7. <el-input v-model="formInline.name" placeholder="输入保险公司查找" clearable />
  8. </el-form-item>
  9. <el-form-item>
  10. <el-button type="primary" @click="companyQuery">查询</el-button>
  11. </el-form-item>
  12. </el-form>
  13. <div>
  14. <el-button type="primary" @click="companyAdd">
  15. <template #icon>
  16. <el-icon>
  17. <Plus />
  18. </el-icon>
  19. </template>
  20. 添加保险公司</el-button>
  21. <div :style="{ height: tableHeight, marginTop: '20px' }">
  22. <el-auto-resizer>
  23. <template #default="{ height, width }">
  24. <el-table-v2 :columns="columns" :data="tabledata" :width="width" :height="height" v-loading="loading"
  25. ref="multipleTableRef" :expand-column-key="expandColumnKey" header-class="header-class">
  26. <template #cell="scope">
  27. <div v-if="scope.column.key == 'option'" class="flex j-s a-c">
  28. <el-button type="primary" link @click="addSubsidiary(scope.rowData)"
  29. v-auth="'organizationlist.edit'"> 添加子公司
  30. </el-button>
  31. <el-dropdown placement="bottom-start">
  32. <span class="el-dropdown-link">
  33. 更 多
  34. </span>
  35. <template #dropdown>
  36. <el-dropdown-menu>
  37. <Auth :value="'organizationlist.delete'">
  38. <el-dropdown-item @click="companyEdit(scope.rowData)">编辑</el-dropdown-item>
  39. <el-dropdown-item @click="companyDel(scope.rowData)">删除</el-dropdown-item>
  40. </Auth>
  41. </el-dropdown-menu>
  42. </template>
  43. </el-dropdown>
  44. </div>
  45. </template>
  46. </el-table-v2>
  47. </template>
  48. </el-auto-resizer>
  49. </div>
  50. </div>
  51. </PageMain>
  52. <el-dialog v-model="dialogVisible" :title="dialogTitle" width="50%" @close="close">
  53. <ElRow :gutter="20">
  54. <el-form :model="cpmpanyform" :inline="true" label-width="120px" :rules="cpmpanyformRules" label-position="top"
  55. ref="FormRef" style="width: 100%;" :size="fromSize">
  56. <ElCol :md="24" :lg="12" v-if="dialogType == 'subsidiaryadd' || dialogType == 'subsidiaryedit'">
  57. <el-form-item label="上级保险公司">
  58. <el-input v-model="cpmpanyform.parentName" disabled />
  59. </el-form-item>
  60. </ElCol>
  61. <ElCol :md="24" :lg="12">
  62. <el-form-item label="保险公司名称" prop="name">
  63. <el-input v-model="cpmpanyform.name" placeholder="请输入保险公司名称" />
  64. </el-form-item>
  65. </ElCol>
  66. <ElCol :md="24" :lg="12">
  67. <el-form-item label="简称" prop="nameSimple">
  68. <el-input v-model="cpmpanyform.nameSimple" placeholder="请输入简称" />
  69. </el-form-item>
  70. </ElCol>
  71. <ElCol :md="24" :lg="12" v-if="dialogType == 'add' || dialogType == 'edit'">
  72. <el-form-item label="类型" prop="type">
  73. <el-select v-model="cpmpanyform.type" placeholder="请选择类型" style="width: 100%;" clearable filterable>
  74. <el-option label="渠道" :value="0" />
  75. <el-option label="财险" :value="1" />
  76. <el-option label="寿险" :value="2" />
  77. </el-select>
  78. </el-form-item>
  79. </ElCol>
  80. <ElCol :md="24" :lg="12" v-if="dialogType == 'add' || dialogType == 'edit'">
  81. <el-form-item label="编码" prop="code">
  82. <el-input v-model="cpmpanyform.code" placeholder="输入4位code编码" show-word-limit maxlength="4" />
  83. </el-form-item>
  84. </ElCol>
  85. <ElCol :md="24" :lg="12" v-if="dialogType == 'subsidiaryadd'">
  86. <el-form-item label="地区">
  87. <el-cascader v-model="provinceoptions" style="width: 100%;" filterable clearable :options="areaOptions"
  88. :props="props" @change="provinceChange" />
  89. </el-form-item>
  90. </ElCol>
  91. <ElCol :md="24" :lg="12">
  92. <el-form-item label="备注">
  93. <el-input v-model="cpmpanyform.remark" placeholder="输入备注" type="textarea" maxlength="500"
  94. show-word-limit />
  95. </el-form-item>
  96. </ElCol>
  97. <ElCol :md="24" :lg="12" v-if="dialogType == 'add' || dialogType == 'edit'">
  98. <el-form-item label="logo">
  99. <el-upload action="#" list-type="picture-card" :auto-upload="false" :on-change="sysIconupload"
  100. ref="upload1" :limit="1" :class="{ disabled: uploadDisabled }" :on-remove="handleRemove">
  101. <img v-if="sysIconList.url" :src="sysIconList.url" class="avatar" style="width: 100%;height: 100%;" />
  102. <el-icon v-else class="avatar-uploader-icon">
  103. <Plus />
  104. </el-icon>
  105. </el-upload>
  106. </el-form-item>
  107. </ElCol>
  108. </el-form>
  109. </ElRow>
  110. <template #footer>
  111. <div class="dialog-footer">
  112. <el-button @click="dialogVisible = false">取消</el-button>
  113. <el-button type="primary" @click="saveInfo(FormRef)">
  114. 保存
  115. </el-button>
  116. </div>
  117. </template>
  118. </el-dialog>
  119. </div>
  120. </template>
  121. <!-- 行为区域 -->
  122. <script lang='tsx' setup>
  123. import api from '@/api';
  124. import { ElTag, ElMessage } from 'element-plus'
  125. import ImagePreview from '@/components/ImagePreview/index.vue';
  126. import { FormRules, FormInstance, ComponentSize, ElMessageBox } from 'element-plus';
  127. interface Column {
  128. key?: string,
  129. dataKey?: string,
  130. title: string,
  131. width: number,
  132. class?: string,
  133. cellRenderer?: any
  134. align?: "left" | "center" | "right"; // align 是可选的,且只能是这三个值之一
  135. }
  136. // 检索
  137. const formInline = reactive({
  138. name: '',
  139. })
  140. //
  141. const cpmpanyform = reactive({
  142. code: "",//编码
  143. companyCode: "",
  144. name: "",//名称
  145. parentId: '0',
  146. parentName: '',
  147. nameSimple: '',//简称
  148. remark: "",//备注
  149. type: "",//类型
  150. logo: "",//图片id
  151. id: '',
  152. })
  153. const validateCode = (_rule: any, value: any, callback: any) => {
  154. // 定义正则表达式,例如:只允许字母、数字,长度在4到10个字符之间
  155. const codeRegex = /^[A-Z0-9]+$/i;
  156. // 判断是否为空
  157. if (!value) {
  158. return callback(new Error('请输入code编码'));
  159. }
  160. // 验证是否符合正则表达式
  161. if (!codeRegex.test(value)) {
  162. return callback(new Error('code编码格式不正确,仅支持4位字母或数字'));
  163. }
  164. // 验证通过
  165. callback();
  166. };
  167. const cpmpanyformRules = ref<FormRules>({
  168. code: [
  169. { required: true, trigger: 'blur', message: '请输入code编码' },
  170. { min: 4, max: 4, message: '仅支持4位字母或数字', trigger: 'blur' },
  171. { validator: validateCode, trigger: 'blur' }
  172. ],
  173. name: [
  174. { required: true, trigger: 'blur', message: '请输入保险公司名称' },
  175. { min: 8, max: 50, message: '请输入8-50个字符', trigger: 'blur' },
  176. ],
  177. nameSimple: [
  178. { required: true, trigger: 'blur', message: '请输入简称' },
  179. ],
  180. type: [
  181. { required: true, trigger: 'change', message: '请选择类型' },
  182. ],
  183. logo: [
  184. { required: true, trigger: 'change', message: '请上传图片' },
  185. ],
  186. });
  187. const sysIconList = reactive({
  188. url: "",
  189. })
  190. const props = {
  191. expandTrigger: 'hover' as const,
  192. value: 'areaCode',
  193. label: 'areaCname',
  194. children: 'child',
  195. checkStrictly: true,
  196. }
  197. const FormRef = ref<FormInstance>()
  198. const provinceoptions = ref()//省市区回显数据
  199. const areaOptions = ref()//省市区数据
  200. const dialogTitle = ref('添加保险公司')//弹窗title
  201. const dialogType = ref('add')//弹窗title add | edit | subsidiaryadd | subsidiaryedit
  202. const fromSize = ref<ComponentSize>('large')//表单大小
  203. const loading = ref(false)
  204. const uploadDisabled = ref(false)//图片回显去掉上传按键
  205. const tableHeight = ref(''); // 初始化表格高度
  206. const multipleTableRef = ref();
  207. const tabledata = ref([]);//树形数据
  208. const dialogVisible = ref(false);//弹窗开关
  209. const expandColumnKey = 'name'//标记可展开列
  210. const columns: Column[] = [
  211. {
  212. key: 'downloadUrl', dataKey: "downloadUrl", title: "logo", width: 100, align: "center",
  213. cellRenderer: ({ cellData: logo }: any) => {
  214. if (logo) {
  215. return <ImagePreview src={logo} width='40px' height='40px'></ImagePreview>;
  216. } else {
  217. return "-";
  218. }
  219. }
  220. },
  221. { key: 'name', dataKey: "name", title: "保险公司名称", width: 500, },
  222. { key: 'companyCode', dataKey: "companyCode", title: "保险公司代码", width: 200, align: "center" },
  223. { key: 'nameSimple', dataKey: "nameSimple", title: "简称", width: 200, align: "center" },
  224. {
  225. key: 'type', dataKey: "type", title: "类型", width: 200, align: "center", cellRenderer: ({ cellData: type }: any) => {
  226. if (type == 1) {
  227. return <ElTag>财险</ElTag>;
  228. } else if (type == 0) {
  229. return <ElTag>渠道</ElTag>;
  230. } else {
  231. return <ElTag>{type}</ElTag>;
  232. }
  233. }
  234. },
  235. {
  236. key: 'option',
  237. title: "操作",
  238. width: 250,
  239. align: 'center',
  240. },
  241. ]
  242. onMounted(() => {
  243. setTimeout(() => {
  244. const tableElement = multipleTableRef.value?.$el as HTMLElement;
  245. if (tableElement) {
  246. const offsetTop = tableElement.offsetTop; // 获取 offsetTop
  247. let height = window.innerHeight;
  248. tableHeight.value = height - offsetTop - 270 + "px";
  249. }
  250. }, 10);
  251. })
  252. onBeforeMount(() => {
  253. findTree();//保险公司树结构查询
  254. queryTreeQuery();//获取区划数据
  255. })
  256. const findTree = () => {
  257. loading.value = true;
  258. api.company.findTree({ name: formInline.name }).then((res: any) => {
  259. if (res.code == '200') {
  260. tabledata.value = res.data;
  261. loading.value = false;
  262. } else {
  263. ElMessage({
  264. type: 'error',
  265. message: res.msg,
  266. plain: true,
  267. })
  268. }
  269. });
  270. }
  271. const companyQuery = () => {
  272. findTree();
  273. }
  274. //
  275. const companyAdd = () => {
  276. dialogVisible.value = true;
  277. dialogTitle.value = '添加保险公司';
  278. dialogType.value = 'add';
  279. }
  280. //添加子公司
  281. const addSubsidiary = (column: any) => {
  282. dialogTitle.value = '添加子公司';
  283. dialogType.value = 'subsidiaryadd';
  284. dialogVisible.value = true;
  285. cpmpanyform.parentName = column.name;
  286. cpmpanyform.parentId = column.id;
  287. cpmpanyform.code = column.code;
  288. }
  289. //删除
  290. const companyDel = (column: any) => {
  291. ElMessageBox.confirm(
  292. '保险公司删除后不可恢复,请谨慎操作',
  293. '确定删除保险公司?',
  294. {
  295. confirmButtonText: '确定删除',
  296. type: 'warning',
  297. center: true,
  298. confirmButtonClass: 'el-button--danger',
  299. }
  300. )
  301. .then(() => {
  302. api.company.CompanyDel(column.id).then((res: any) => {
  303. if (res.code == '200') {
  304. findTree();
  305. ElMessage({
  306. type: 'success',
  307. message: res.msg,
  308. plain: true,
  309. })
  310. } else {
  311. }
  312. });
  313. })
  314. .catch(() => {
  315. })
  316. }
  317. // 编辑
  318. const companyEdit = (column: any) => {
  319. if (column.parentId == '0') {
  320. dialogType.value = 'edit';
  321. dialogTitle.value = '编辑';
  322. dialogVisible.value = true;
  323. cpmpanyform.id = column.id;
  324. cpmpanyform.code = column.code;
  325. cpmpanyform.companyCode = column.companyCode;
  326. cpmpanyform.name = column.name;
  327. cpmpanyform.parentId = column.parentId;
  328. cpmpanyform.nameSimple = column.nameSimple;
  329. cpmpanyform.remark = column.remark;
  330. cpmpanyform.type = column.type;
  331. cpmpanyform.logo = column.logo;
  332. sysIconList.url = column.downloadUrl;
  333. } else {
  334. dialogType.value = 'subsidiaryedit';
  335. dialogTitle.value = '编辑';
  336. dialogVisible.value = true;
  337. cpmpanyform.id = column.id;
  338. cpmpanyform.code = column.code;
  339. cpmpanyform.companyCode = column.companyCode;
  340. cpmpanyform.name = column.name;
  341. cpmpanyform.nameSimple = column.nameSimple;
  342. cpmpanyform.parentId = column.parentId;
  343. cpmpanyform.parentName = column.parentName;
  344. cpmpanyform.remark = column.remark;
  345. sysIconList.url = column.downloadUrl;
  346. }
  347. // (Object.keys(cpmpanyform) as (keyof typeof cpmpanyform)[]).forEach((key) => {
  348. // if (key in column) {
  349. // cpmpanyform[key] = column[key] as any;
  350. // }
  351. // });
  352. }
  353. //获取区划数据
  354. const queryTreeQuery = () => {
  355. api.dept.queryTree().then((res: any) => {
  356. if (res.code == '200') {
  357. areaOptions.value = res.data;
  358. } else {
  359. ElMessage({
  360. type: 'success',
  361. message: res.msg,
  362. plain: true,
  363. })
  364. }
  365. });
  366. }
  367. const provinceChange = (value: any) => {
  368. cpmpanyform.companyCode = cpmpanyform.code + '1' + value[value.length - 1];
  369. }
  370. const saveInfo = async (formEl: FormInstance | undefined) => {
  371. if (!formEl) return
  372. await formEl.validate((valid) => {
  373. if (valid) {
  374. if (dialogType.value == 'add') {
  375. cpmpanyform.companyCode = cpmpanyform.code + '1000000';
  376. api.company.saveInsCompany({ ...cpmpanyform }).then((res: any) => {
  377. if (res.code == '200') {
  378. dialogVisible.value = false;
  379. findTree();
  380. ElMessage({
  381. type: 'success',
  382. message: res.msg,
  383. plain: true,
  384. })
  385. }
  386. });
  387. } else if (dialogType.value == 'subsidiaryadd') {
  388. api.company.saveInsCompany({ ...cpmpanyform }).then((res: any) => {
  389. if (res.code == '200') {
  390. dialogVisible.value = false;
  391. findTree();
  392. ElMessage({
  393. type: 'success',
  394. message: res.msg,
  395. plain: true,
  396. })
  397. }
  398. });
  399. } else {
  400. api.company.editInsCompany({ ...cpmpanyform }).then((res: any) => {
  401. if (res.code == '200') {
  402. dialogVisible.value = false;
  403. findTree();
  404. ElMessage({
  405. type: 'success',
  406. message: res.msg,
  407. plain: true,
  408. })
  409. }
  410. });
  411. }
  412. } else {
  413. ElMessage({
  414. type: 'error',
  415. message: '信息不完整',
  416. plain: true,
  417. })
  418. }
  419. })
  420. }
  421. const sysIconupload = (file: any) => {
  422. let files = file.raw;
  423. const params = new FormData(); // 声明formData数据类型
  424. params.append("file", files);
  425. api.toolApi.fileupload(params).then((res: any) => {
  426. if (res.code == 200) {
  427. cpmpanyform.logo = res.data.id;
  428. uploadDisabled.value = true;
  429. }
  430. })
  431. }
  432. const handleRemove = () => {
  433. sysIconList.url = '';
  434. uploadDisabled.value = false;
  435. }
  436. const close = () => {
  437. cpmpanyform.code = '';
  438. cpmpanyform.name = '';
  439. cpmpanyform.parentId = '0';
  440. cpmpanyform.parentName = '';
  441. cpmpanyform.nameSimple = '';
  442. cpmpanyform.remark = '';
  443. cpmpanyform.type = '';
  444. cpmpanyform.logo = '';
  445. provinceoptions.value = [];
  446. sysIconList.url = '';
  447. }
  448. </script>
  449. <style scoped lang="scss">
  450. :deep(.header-class .el-table-v2__header-cell) {
  451. padding: 10px 20px;
  452. font-size: 15px;
  453. color: #333;
  454. background-color: #eef1f6;
  455. border-bottom: 1px solid #eef1f6;
  456. }
  457. :deep(.el-table-v2__header-row) {
  458. justify-content: space-between;
  459. background-color: #eef1f6;
  460. }
  461. :deep(.el-table-v2__row) {
  462. justify-content: space-between;
  463. }
  464. :deep(.el-table-v2__expand-icon) {
  465. margin: 0;
  466. }
  467. :deep(.el-table-v2__cell-text) {
  468. margin-left: 10px;
  469. }
  470. :deep(.el-dropdown-link) {
  471. display: flex;
  472. align-items: center;
  473. margin-left: 15px;
  474. color: var(--el-color-primary);
  475. cursor: pointer;
  476. }
  477. .disabled :deep(.el-upload--picture-card) {
  478. opacity: 0;
  479. }
  480. </style>
  481. <!-- 样式区域 -->