tenantIndex.vue 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284
  1. <template>
  2. <div class="app-container">
  3. <el-form
  4. :model="queryParams"
  5. ref="queryForm"
  6. size="small"
  7. :inline="true"
  8. v-show="showSearch"
  9. label-width="68px"
  10. >
  11. <el-form-item label="租户名称" prop="tenantName">
  12. <el-input
  13. v-model="queryParams.tenantName"
  14. placeholder="请输入租户名称"
  15. clearable
  16. @keyup.enter.native="handleQuery"
  17. />
  18. </el-form-item>
  19. <el-form-item label="租户编号" prop="tenantCode">
  20. <el-input
  21. v-model="queryParams.tenantCode"
  22. placeholder="请输入租户编号"
  23. clearable
  24. @keyup.enter.native="handleQuery"
  25. />
  26. </el-form-item>
  27. <el-form-item label="负责人" prop="owner">
  28. <el-input
  29. v-model="queryParams.owner"
  30. placeholder="请输入负责人"
  31. clearable
  32. @keyup.enter.native="handleQuery"
  33. />
  34. </el-form-item>
  35. <el-form-item label="联系方式" prop="contactInfo">
  36. <el-input
  37. v-model="queryParams.contactInfo"
  38. placeholder="请输入联系方式"
  39. clearable
  40. @keyup.enter.native="handleQuery"
  41. />
  42. </el-form-item>
  43. <el-form-item label="地址" prop="address">
  44. <el-input
  45. v-model="queryParams.address"
  46. placeholder="请输入地址"
  47. clearable
  48. @keyup.enter.native="handleQuery"
  49. />
  50. </el-form-item>
  51. <el-form-item>
  52. <el-button
  53. type="primary"
  54. icon="el-icon-search"
  55. size="mini"
  56. @click="handleQuery"
  57. >搜索
  58. </el-button
  59. >
  60. <el-button icon="el-icon-refresh" size="mini" @click="resetQuery"
  61. >重置
  62. </el-button
  63. >
  64. </el-form-item>
  65. </el-form>
  66. <el-row :gutter="10" class="mb8">
  67. <el-col :span="1.5">
  68. <el-button
  69. type="primary"
  70. plain
  71. icon="el-icon-plus"
  72. size="mini"
  73. @click="handleAdd"
  74. v-hasPermi="['system:tenant:add']"
  75. >新增
  76. </el-button>
  77. </el-col>
  78. <el-col :span="1.5">
  79. <el-button
  80. v-if="selection.length == 0"
  81. type="warning"
  82. plain
  83. icon="el-icon-download"
  84. size="mini"
  85. @click="handleExport"
  86. v-hasPermi="['system:tenant:export']"
  87. >导出
  88. </el-button>
  89. <ExcelDownLoad
  90. v-else
  91. :headerList="headerList"
  92. :fieldList="selection"
  93. :excelTitle="excelTitle"
  94. ></ExcelDownLoad>
  95. </el-col>
  96. <right-toolbar
  97. :showSearch.sync="showSearch"
  98. @queryTable="getList"
  99. ></right-toolbar>
  100. </el-row>
  101. <el-table
  102. :data="tenantList"
  103. style="width: 100%"
  104. row-key="tenantId"
  105. border
  106. lazy
  107. :load="load"
  108. :tree-props="{children: 'children', hasChildren:'hasChildren' }"
  109. >
  110. <el-table-column label="租户ID" align="center" prop="tenantId"/>
  111. <el-table-column label="租户名称" align="center" prop="tenantName"/>
  112. <el-table-column label="租户编号" align="center" prop="tenantCode"/>
  113. <el-table-column label="负责人" align="center" prop="owner"/>
  114. <el-table-column label="联系方式" align="center" prop="contactInfo"/>
  115. <el-table-column label="地址" align="center" prop="address"/>
  116. <el-table-column label="租户父级ID" align="center" prop="tenantParentId"/>
  117. <el-table-column label="客户端访问地址" align="center" prop="tenantClientLoginUrl"/>
  118. <el-table-column label="工具端访问地址" align="center" prop="tenantToolLoginUrl"/>
  119. <el-table-column label="租户等级" align="center" prop="tenantGrade"/>
  120. <el-table-column label="到期天数" align="center" prop="tenantExpirationTime"/>
  121. <el-table-column
  122. label="操作"
  123. align="center"
  124. class-name="small-padding fixed-width"
  125. >
  126. <template slot-scope="scope">
  127. <el-dropdown>
  128. <el-button type="warning" plain size="small">
  129. 处理<i class="el-icon-arrow-down el-icon--right"></i>
  130. </el-button>
  131. <el-dropdown-menu slot="dropdown">
  132. <el-dropdown-item>
  133. <el-button
  134. size="mini"
  135. type="text"
  136. icon="el-icon-edit"
  137. @click="handleUpdate(scope.row)"
  138. v-hasPermi="['system:tenant:edit']"
  139. >修改
  140. </el-button>
  141. </el-dropdown-item>
  142. <el-dropdown-item>
  143. <el-button
  144. size="mini"
  145. type="text"
  146. icon="el-icon-delete"
  147. @click="handleDelete(scope.row)"
  148. v-hasPermi="['system:tenant:remove']"
  149. >删除
  150. </el-button>
  151. </el-dropdown-item>
  152. <el-dropdown-item>
  153. <el-button
  154. size="mini"
  155. type="text"
  156. icon="el-icon-position"
  157. @click="bindDatasource(scope.row)"
  158. v-show="scope.row.datasourceId == null"
  159. >绑定数据源
  160. </el-button>
  161. </el-dropdown-item>
  162. <el-dropdown-item>
  163. <el-button
  164. size="mini"
  165. type="text"
  166. icon="el-icon-s-custom"
  167. @click="openTenantExpirationTime(scope.row)"
  168. v-hasPermi="['system:tenant:remove']"
  169. >激活租户
  170. </el-button>
  171. </el-dropdown-item>
  172. <el-dropdown-item>
  173. <el-button
  174. size="mini"
  175. type="text"
  176. icon="el-icon-s-open"
  177. @click="openLoginConfig(scope.row)"
  178. v-hasPermi="['system:tenant:remove']"
  179. >配置登录页
  180. </el-button>
  181. </el-dropdown-item>
  182. </el-dropdown-menu>
  183. </el-dropdown>
  184. </template>
  185. </el-table-column>
  186. </el-table>
  187. <el-table
  188. v-loading="loading"
  189. :data="tenantList"
  190. @selection-change="handleSelectionChange"
  191. >
  192. <el-table-column type="selection" width="55" align="center"/>
  193. <el-table-column label="租户ID" align="center" prop="tenantId"/>
  194. <el-table-column label="租户名称" align="center" prop="tenantName"/>
  195. <el-table-column label="租户编号" align="center" prop="tenantCode"/>
  196. <el-table-column label="负责人" align="center" prop="owner"/>
  197. <el-table-column label="联系方式" align="center" prop="contactInfo"/>
  198. <el-table-column label="地址" align="center" prop="address"/>
  199. <el-table-column label="租户父级ID" align="center" prop="tenantParentId"/>
  200. <el-table-column label="客户端访问地址" align="center" prop="tenantClientLoginUrl"/>
  201. <el-table-column label="工具端访问地址" align="center" prop="tenantToolLoginUrl"/>
  202. <el-table-column label="租户等级" align="center" prop="tenantGrade"/>
  203. <el-table-column
  204. label="到期天数"
  205. align="center"
  206. prop="tenantExpirationTime"
  207. />
  208. <el-table-column
  209. label="操作"
  210. align="center"
  211. class-name="small-padding fixed-width"
  212. >
  213. <template slot-scope="scope">
  214. <el-dropdown>
  215. <el-button type="warning" plain size="small">
  216. 处理<i class="el-icon-arrow-down el-icon--right"></i>
  217. </el-button>
  218. <el-dropdown-menu slot="dropdown">
  219. <el-dropdown-item>
  220. <el-button
  221. size="mini"
  222. type="text"
  223. icon="el-icon-edit"
  224. @click="handleUpdate(scope.row)"
  225. v-hasPermi="['system:tenant:edit']"
  226. >修改
  227. </el-button>
  228. </el-dropdown-item>
  229. <el-dropdown-item>
  230. <el-button
  231. size="mini"
  232. type="text"
  233. icon="el-icon-delete"
  234. @click="handleDelete(scope.row)"
  235. v-hasPermi="['system:tenant:remove']"
  236. >删除
  237. </el-button>
  238. </el-dropdown-item>
  239. <el-dropdown-item>
  240. <el-button
  241. size="mini"
  242. type="text"
  243. icon="el-icon-position"
  244. @click="bindDatasource(scope.row)"
  245. v-show="scope.row.datasourceId == null"
  246. >绑定数据源
  247. </el-button>
  248. </el-dropdown-item>
  249. <el-dropdown-item>
  250. <el-button
  251. size="mini"
  252. type="text"
  253. icon="el-icon-s-custom"
  254. @click="openTenantExpirationTime(scope.row)"
  255. v-hasPermi="['system:tenant:remove']"
  256. >激活租户
  257. </el-button>
  258. </el-dropdown-item>
  259. <el-dropdown-item>
  260. <el-button
  261. size="mini"
  262. type="text"
  263. icon="el-icon-s-open"
  264. @click="openLoginConfig(scope.row)"
  265. v-hasPermi="['system:tenant:remove']"
  266. >配置登录页
  267. </el-button>
  268. </el-dropdown-item>
  269. </el-dropdown-menu>
  270. </el-dropdown>
  271. </template>
  272. </el-table-column>
  273. </el-table>
  274. <pagination
  275. v-show="total > 0"
  276. :total="total"
  277. :page.sync="queryParams.pageNum"
  278. :limit.sync="queryParams.pageSize"
  279. @pagination="getList"
  280. />
  281. <!-- 添加或修改租户信息对话框 -->
  282. <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
  283. <el-form ref="form" :model="form" :rules="rules" label-width="80px">
  284. <el-form-item label="选择上级租户" prop="tenantParentId">
  285. <el-cascader v-model="form.tenantParentId"
  286. :options="tenantAllList"
  287. :props="{ checkStrictly: true ,label:'tenantName',value:'tenantId' }" clearable
  288. ></el-cascader>
  289. </el-form-item>
  290. <el-form-item label="租户名称" prop="tenantName">
  291. <el-input v-model="form.tenantName" placeholder="请输入租户名称"/>
  292. </el-form-item>
  293. <el-form-item label="租户编号" prop="tenantCode">
  294. <el-input v-model="form.tenantCode" placeholder="请输入租户编号"/>
  295. </el-form-item>
  296. <el-form-item label="负责人" prop="owner">
  297. <el-input v-model="form.owner" placeholder="请输入负责人"/>
  298. </el-form-item>
  299. <el-form-item label="联系方式" prop="contactInfo">
  300. <el-input v-model="form.contactInfo" placeholder="请输入联系方式"/>
  301. </el-form-item>
  302. <el-form-item label="地址" prop="address">
  303. <el-input v-model="form.address" placeholder="请输入地址"/>
  304. </el-form-item>
  305. <el-form-item label="客户端访问地址" prop="tenantClientLoginUrl">
  306. <el-input v-model="form.tenantClientLoginUrl" placeholder="请输入地址"/>
  307. </el-form-item>
  308. <el-form-item label="工具端访问地址" prop="tenantToolLoginUrl">
  309. <el-input v-model="form.tenantToolLoginUrl" placeholder="请输入地址"/>
  310. </el-form-item>
  311. <el-form-item label="租户等级" prop="tenantGrade">
  312. <el-input v-model="form.tenantGrade" placeholder="请输入地址"/>
  313. </el-form-item>
  314. </el-form>
  315. <div slot="footer" class="dialog-footer">
  316. <el-button type="primary" @click="submitForm">确 定</el-button>
  317. <el-button @click="cancel">取 消</el-button>
  318. </div>
  319. </el-dialog>
  320. <!-- 添加或修改数据源信息对话框 -->
  321. <el-dialog
  322. :title="dataSourceTitle"
  323. :visible.sync="dataSourceOpen"
  324. width="500px"
  325. append-to-body
  326. class="loadingClass"
  327. >
  328. <el-radio-group
  329. v-model="dataSourceType"
  330. class="mb5"
  331. @input="dataSourceTypeChange"
  332. >
  333. <el-radio-button :label="true">公网</el-radio-button>
  334. <el-radio-button :label="false">内网</el-radio-button>
  335. </el-radio-group>
  336. <el-form
  337. ref="dataSourceForm"
  338. :model="dataSourceForm"
  339. :rules="dataSourceFormRules"
  340. label-width="120px"
  341. >
  342. <el-form-item label="数据源类型" prop="databaseType">
  343. <el-select
  344. v-model="dataSourceForm.databaseType"
  345. :placeholder="palcemsg"
  346. @change="selecthandle"
  347. :disabled="dataSourceType"
  348. >
  349. <el-option
  350. v-for="item in dict.type.datasource_type"
  351. :key="item.value"
  352. :label="item.label"
  353. :value="item.value"
  354. ></el-option>
  355. </el-select>
  356. </el-form-item>
  357. <el-form-item label="数据库名称" prop="databaseName">
  358. <el-input
  359. v-model="dataSourceForm.databaseName"
  360. placeholder="请输入数据库名称"
  361. />
  362. </el-form-item>
  363. <el-form-item label="租户管理员账号" prop="tenantAccount">
  364. <el-input
  365. v-model="dataSourceForm.tenantAccount"
  366. placeholder="请输入租户管理员账号"
  367. />
  368. </el-form-item>
  369. <!-- !dataSourceType -->
  370. <el-form-item
  371. label="数据库IP"
  372. v-show="!dataSourceType"
  373. prop="databaseIp"
  374. >
  375. <el-input
  376. v-model="dataSourceForm.databaseIp"
  377. placeholder="请输数据库IP"
  378. />
  379. </el-form-item>
  380. <el-form-item label="用户名" v-show="!dataSourceType" prop="username">
  381. <el-input
  382. v-model="dataSourceForm.username"
  383. placeholder="请输入用户名"
  384. />
  385. </el-form-item>
  386. <el-form-item label="密码" v-show="!dataSourceType" prop="password">
  387. <el-input
  388. v-model="dataSourceForm.password"
  389. placeholder="请输入密码"
  390. />
  391. </el-form-item>
  392. <el-form-item label="端口号" v-show="!dataSourceType" prop="portNumber">
  393. <el-input
  394. v-model="dataSourceForm.portNumber"
  395. placeholder="请输入端口号"
  396. />
  397. </el-form-item>
  398. </el-form>
  399. <div slot="footer" class="dialog-footer">
  400. <el-button
  401. type="primary"
  402. @click="submitForm1"
  403. :disabled="dialogLoading"
  404. :loading="dialogLoading"
  405. >{{ dialogLoading ? '绑定中' : '确 定' }}
  406. </el-button
  407. >
  408. <el-button @click="cancel1">取 消</el-button>
  409. </div>
  410. </el-dialog>
  411. <!-- 激活租户弹出层-->
  412. <el-dialog
  413. title="激活租户"
  414. :visible.sync="tenantExpirationTimeOpen"
  415. width="500px"
  416. append-to-body
  417. >
  418. <el-form
  419. ref="tenantExpirationTimeFrom"
  420. :model="tenantExpirationTimeFrom"
  421. :rules="rulesTenantExpirationTime"
  422. label-width="80px"
  423. >
  424. <el-form-item
  425. label="激活租户"
  426. prop="tenantExpirationTime"
  427. label-width="110px"
  428. >
  429. <el-input
  430. v-model="tenantExpirationTimeFrom.tenantExpirationTime"
  431. placeholder="请输入激活码"
  432. />
  433. </el-form-item>
  434. <el-form-item class="btn">
  435. <el-button
  436. type="primary"
  437. @click="activationOperationMethod('tenantExpirationTimeFrom')"
  438. >确 定
  439. </el-button
  440. >
  441. <el-button @click="tanentCancel">取 消</el-button>
  442. </el-form-item>
  443. </el-form>
  444. </el-dialog>
  445. <!-- 登录页面配置信息列表 -->
  446. <el-dialog
  447. title="配置登录页"
  448. width="800px"
  449. :visible.sync="loginOpen"
  450. append-to-body
  451. >
  452. <el-form
  453. ref="loginFormRef"
  454. :model="loginForm"
  455. :inline="true"
  456. :rules="rules"
  457. label-width="80px"
  458. >
  459. <el-form-item prop="loginPageNumber">
  460. <span slot="label">
  461. <el-tooltip
  462. content="请在登录时的url后拼接参数:tenantId={编号}"
  463. placement="top"
  464. >
  465. <i class="el-icon-question"></i>
  466. </el-tooltip>
  467. 编号:
  468. </span>
  469. <el-input
  470. v-model="loginForm.loginPageNumber"
  471. placeholder="请输入登录页面编号"
  472. disabled
  473. />
  474. </el-form-item>
  475. <!-- <el-col :span="8"> -->
  476. <el-form-item label="标题:" prop="loginPageTitle">
  477. <el-input
  478. v-model="loginForm.loginPageTitle"
  479. placeholder="请输入登录页面标题"
  480. />
  481. </el-form-item>
  482. <!-- </el-col> -->
  483. <!-- <el-col :span="8"> -->
  484. <el-form-item label="描述:" prop="loginPageDescription">
  485. <span slot="label">
  486. <el-tooltip
  487. content="推荐长度为8个汉字,可使用<br/>换行"
  488. placement="top"
  489. >
  490. <i class="el-icon-question"></i>
  491. </el-tooltip>
  492. 描述:
  493. </span>
  494. <el-input
  495. v-model="loginForm.loginPageDescription"
  496. type="textarea"
  497. placeholder="请输入内容"
  498. />
  499. </el-form-item>
  500. <!-- </el-col>
  501. <el-col :span="8"> -->
  502. <el-form-item label="窗口标题:" prop="windowTitle">
  503. <el-input
  504. v-model="loginForm.windowTitle"
  505. placeholder="请输入窗口标题"
  506. />
  507. </el-form-item>
  508. <!-- </el-col> -->
  509. <!-- <el-col :span="8"> -->
  510. <el-form-item prop="loginPageLogo">
  511. <span slot="label">
  512. <el-tooltip content="推荐图片大小为194*64px" placement="top">
  513. <i class="el-icon-question"></i>
  514. </el-tooltip>
  515. logo:
  516. </span>
  517. <image-upload :limit="1" v-model="loginForm.loginPageLogo"/>
  518. </el-form-item>
  519. <!-- </el-col> -->
  520. <!-- <el-col :span="8"> -->
  521. <el-form-item prop="loginPageBackgroundImage">
  522. <span slot="label">
  523. <el-tooltip content="推荐图片大小为1400*900px" placement="top">
  524. <i class="el-icon-question"></i>
  525. </el-tooltip>
  526. 背景图:
  527. </span>
  528. <image-upload
  529. :limit="1"
  530. v-model="loginForm.loginPageBackgroundImage"
  531. />
  532. </el-form-item>
  533. <!-- </el-col> -->
  534. <!-- <el-col :span="8"> -->
  535. <!-- <el-form-item label="窗口logo:" prop="windowLogo">
  536. <image-upload
  537. :fileType="['png']"
  538. :limit="1"
  539. :uploadUrl="'/common/uploadAndConvert'"
  540. v-model="loginForm.windowLogo"
  541. />
  542. </el-form-item> -->
  543. <!-- </el-col> -->
  544. </el-form>
  545. <div slot="footer" class="dialog-footer">
  546. <el-button type="primary" @click="submitLoginForm">确 定</el-button>
  547. <el-button @click="cancelLoginForm">取 消</el-button>
  548. </div>
  549. </el-dialog>
  550. </div>
  551. </template>
  552. <script>
  553. import {
  554. listTenant,
  555. getTenant,
  556. delTenant,
  557. addTenant,
  558. updateTenant,
  559. bindDatasource,
  560. selectAllUser,
  561. createTenant,
  562. initTenantMenuData,
  563. activationOperation,
  564. getTenantChildrenInfo, getTenantAllList
  565. } from '@/api/system/tenant'
  566. import {getDataSourceInfo, insertDataSource} from '@/api/system/data'
  567. import {
  568. listConfiguration,
  569. getConfiguration,
  570. delConfiguration,
  571. addConfiguration,
  572. updateConfiguration
  573. } from '@/api/system/configuration'
  574. import {servicesLoading} from '@/utils/zkqy'
  575. import {getIsExistUser} from '@/api/system/user'
  576. import ExcelDownLoad from '@/components/ExcelDownLoad/index.vue'
  577. export default {
  578. name: 'Tenant',
  579. dicts: [
  580. 'datasource_type',
  581. 'sqlserver_connection_information',
  582. 'mysql_connection_information',
  583. 'dm_connection_information',
  584. 'orcale_connection_information',
  585. 'system_login_url'
  586. ],
  587. components: {
  588. ExcelDownLoad
  589. },
  590. data() {
  591. return {
  592. tenantAllList: [],
  593. // 登录页面数据
  594. isEdit: false,
  595. loginOpen: false,
  596. loginForm: {
  597. loginPageNumber: '',
  598. loginPageTitle: '',
  599. loginPageDescription: '',
  600. loginPageLogo: '',
  601. loginPageBackgroundImage: '',
  602. windowTitle: '',
  603. windowLogo: '',
  604. tenantId: ''
  605. },
  606. // 前端导出数据
  607. selection: [],
  608. headerList: {
  609. 租户名称: 'tenantName',
  610. 租户编号: 'tenantCode',
  611. 负责人: 'owner',
  612. 联系方式: 'contactInfo',
  613. 地址: 'address',
  614. 是否删除: 'isDel'
  615. },
  616. excelTitle: 'tenant',
  617. // 弹窗的加载提示
  618. dialogLoading: false,
  619. // 遮罩层
  620. loading: true,
  621. // 选中数组
  622. ids: [],
  623. // 非单个禁用
  624. single: true,
  625. // 非多个禁用
  626. multiple: true,
  627. // 显示搜索条件
  628. showSearch: true,
  629. // 总条数
  630. total: 0,
  631. // 租户信息表格数据
  632. tenantList: [],
  633. // 弹出层标题
  634. title: '',
  635. // 是否显示弹出层
  636. open: false,
  637. // 所有用户信息
  638. allUser: [],
  639. // 查询参数
  640. queryParams: {
  641. pageNum: 1,
  642. pageSize: 10,
  643. tenantName: null,
  644. tenantCode: null,
  645. owner: null,
  646. contactInfo: null,
  647. address: null
  648. },
  649. // 当前编辑租户的信息
  650. currentTenantInfo: {},
  651. // 表单参数
  652. form: {},
  653. // 表单校验
  654. rules: {
  655. tenantName: [
  656. {required: true, message: '租户名称不能为空', trigger: 'blur'}
  657. ],
  658. tenantCode: [
  659. {required: true, message: '租户编号不能为空', trigger: 'blur'}
  660. ],
  661. tenantParentId: [
  662. {required: true, message: '请选择上级租户', trigger: 'blur'}
  663. ]
  664. },
  665. //数据源表单参数
  666. dataSourceType: true, //true:公网 false:内网
  667. dataSourceForm: {
  668. databaseType: '',
  669. databaseName: '',
  670. tenantAccount: '',
  671. databaseIp: '',
  672. username: '',
  673. password: '',
  674. portNumber: ''
  675. },
  676. dataSourceTitle: '',
  677. dataSourceOpen: false,
  678. fromTenantId: null,
  679. dataSourceFormRules: {
  680. databaseType: [
  681. {required: true, message: '数据源类型不能为空', trigger: 'change'}
  682. ],
  683. databaseName: [
  684. {required: true, message: '数据库名不能为空', trigger: 'blur'},
  685. {validator: this.databaseNameValidator, trigger: 'blur'}
  686. ],
  687. tenantAccount: [
  688. {
  689. required: true,
  690. message: '租户管理员账号不能为空',
  691. trigger: 'change'
  692. },
  693. {validator: this.tenantAccountValidator, trigger: 'blur'}
  694. ],
  695. databaseIp: [
  696. {required: true, message: '数据库IP不能为空', trigger: 'blur'}
  697. ],
  698. username: [
  699. {required: true, message: '用户名不能为空', trigger: 'blur'}
  700. ],
  701. password: [
  702. {required: true, message: '密码不能为空', trigger: 'blur'}
  703. ],
  704. portNumber: [
  705. {required: true, message: '端口号不能为空', trigger: 'blur'}
  706. ]
  707. },
  708. //租户激活码弹窗表单
  709. tenantExpirationTimeFrom: {
  710. tenantId: null,
  711. tenantExpirationTime: ''
  712. },
  713. //租户激活码弹窗标题
  714. tenantExpirationTimeOpen: false,
  715. //租户激活码规则验证
  716. rulesTenantExpirationTime: {
  717. tenantExpirationTime: [
  718. {required: true, message: '请输入租户激活码', trigger: 'blur'}
  719. ]
  720. },
  721. currentPage: '',
  722. // 已存在的数据库名称
  723. databaseNameList: [],
  724. tableData1: [{
  725. id: 1,
  726. date: '2016-05-02',
  727. name: '王小虎',
  728. address: '上海市普陀区金沙江路 1518 弄'
  729. }, {
  730. id: 2,
  731. date: '2016-05-04',
  732. name: '王小虎',
  733. address: '上海市普陀区金沙江路 1517 弄'
  734. }, {
  735. id: 3,
  736. date: '2016-05-01',
  737. name: '王小虎',
  738. address: '上海市普陀区金沙江路 1519 弄',
  739. hasChildren: true
  740. }, {
  741. id: 4,
  742. date: '2016-05-03',
  743. name: '王小虎',
  744. address: '上海市普陀区金沙江路 1516 弄'
  745. }]
  746. }
  747. },
  748. computed: {
  749. palcemsg() {
  750. return this.dataSourceType ? 'mysql' : '请选择数据源类型'
  751. }
  752. },
  753. created() {
  754. this.getList()
  755. this.selectAllUser()
  756. },
  757. methods: {
  758. load(tree, treeNode, resolve) {
  759. console.log(tree, treeNode, resolve)
  760. // 根据当前租户id查询子租户
  761. getTenantChildrenInfo(tree.tenantId).then(res => {
  762. if (res.data != null) {
  763. resolve(res.data)
  764. } else {
  765. resolve({})
  766. }
  767. })
  768. },
  769. // 查询所有平台所有租户
  770. getTenantAllList() {
  771. getTenantAllList().then((response) => {
  772. let tenantAllListOne = this.handleTree(response.rows, 'tenantId', 'tenantParentId')
  773. this.tenantAllList = [
  774. {"tenantId": 0, "tenantName": "顶级租户"},
  775. ...tenantAllListOne
  776. ]
  777. })
  778. },
  779. buildTree(data, parentId = null) {
  780. const children = data.filter(item => item.tenantParentId === parentId)
  781. return children.map(child => ({
  782. value: child.tenantId,
  783. label: child.tenantName,
  784. children: this.buildTree(data, child.tenantId) // 将 child.tenant_id 作为下一层的 parentId
  785. }))
  786. },
  787. transformTenantsToCascaderOptions(tenants) {
  788. console.log(tenants)
  789. const options = []
  790. const map = {} // 用于存储每个tenant的引用,以便后续添加children
  791. tenants.forEach(tenant => {
  792. const {tenantId, tenantName, tenantParentId} = tenant
  793. const option = {
  794. value: tenantId,
  795. label: tenantName,
  796. children: [] // 初始化children数组
  797. }
  798. if (tenantParentId === null) {
  799. // 如果没有父级,说明是顶级租户,直接添加到options中
  800. options.push(option)
  801. } else {
  802. // 如果有父级,则先查找父级租户在map中的引用,并添加到其children数组中
  803. if (!map[tenantParentId]) {
  804. // 如果父级租户还没被处理过,先创建一个空的引用
  805. map[tenantParentId] = {children: []}
  806. }
  807. map[tenantParentId].children.push(option)
  808. }
  809. // 将当前租户添加到map中,方便后续查找
  810. map[tenantId] = option
  811. })
  812. // 遍历map,将顶级租户的children填充完整
  813. Object.values(map).forEach(option => {
  814. if (!options.includes(option)) {
  815. // 如果这个选项不是顶级租户,则将其添加到某个顶级租户的children中
  816. const parentOption = options.find(o => o.children.includes(option))
  817. if (parentOption) {
  818. parentOption.children.push(option)
  819. }
  820. }
  821. })
  822. console.log(options)
  823. return options
  824. },
  825. // 提交登录页配置数据
  826. submitLoginForm() {
  827. this.$refs.loginFormRef?.validate(async (valid) => {
  828. if (valid) {
  829. console.log(this.loginForm)
  830. let res = {},
  831. msg = ''
  832. if (this.isEdit) {
  833. res = await updateConfiguration(this.loginForm)
  834. msg = '修改'
  835. } else {
  836. res = await addConfiguration(this.loginForm)
  837. msg = '保存'
  838. }
  839. if (res.code == 200) {
  840. this.$message.success(`${msg}成功`)
  841. this.loginOpen = false
  842. } else {
  843. this.$message.error(`${msg}失败,请检查网络`)
  844. }
  845. } else {
  846. console.log(`${msg}失败,请检查网络`)
  847. return false
  848. }
  849. })
  850. },
  851. // 取消登录页配置
  852. cancelLoginForm() {
  853. this.loginOpen = false
  854. },
  855. // 编辑租户登录页配置
  856. async openLoginConfig(row) {
  857. try {
  858. let res = await getConfiguration(row.tenantId)
  859. if (res.code == 200) {
  860. if (res.data) {
  861. this.loginForm = res.data
  862. this.isEdit = true
  863. } else {
  864. this.resetloginForm()
  865. this.isEdit = false
  866. }
  867. // 目前一个租户只能有一个配置项故使用租户唯一编码
  868. this.loginForm.loginPageNumber = row.tenantCode
  869. this.loginForm.tenantId = row.tenantId
  870. this.loginOpen = true
  871. } else {
  872. this.$message.error('网络异常,请稍后再试')
  873. }
  874. } catch (error) {
  875. }
  876. },
  877. // 获取所用用户名,作校验用
  878. async selectAllUser() {
  879. let res = await selectAllUser()
  880. if (res.code == 200) {
  881. this.allUser = res.data
  882. } else {
  883. console.log(res.msg)
  884. }
  885. },
  886. // 重置login配置表单数据
  887. resetloginForm() {
  888. this.loginForm = {
  889. loginPageNumber: '',
  890. loginPageTitle: '',
  891. loginPageDescription: '',
  892. loginPageLogo: '',
  893. loginPageBackgroundImage: '',
  894. windowTitle: '',
  895. windowLogo: '',
  896. tenantId: ''
  897. }
  898. },
  899. // 租户名自定义校验规则
  900. async tenantAccountValidator(rule, value, callback) {
  901. // let isRepeat = this.allUser.filter((item) => item.userName == value);
  902. // if (isRepeat.length !== 0) {
  903. // callback(new Error("租户账号重复"));
  904. // } else {
  905. // callback();
  906. // }
  907. if (value) {
  908. await getIsExistUser({userName: value}).then((res) => {
  909. if (res.code == 200) {
  910. if (res.data) {
  911. callback()
  912. } else {
  913. callback(new Error('租户管理员账号已存在'))
  914. }
  915. } else {
  916. callback(new Error('租户管理员账号校验失败,请重新输入'))
  917. }
  918. })
  919. }
  920. callback()
  921. },
  922. // 数据库名自定义校验规则--请求后端校验
  923. // async databaseNameValidator(rule, value, callback) {
  924. // if (value) {
  925. // await getDataSourceInfo({ databaseName: value }).then((res) => {
  926. // if (res.code == 200) {
  927. // if (res.data) {
  928. // callback();
  929. // } else {
  930. // callback(new Error("数据库名已存在"));
  931. // }
  932. // } else {
  933. // callback(new Error("数据库名校验失败,请重新输入"));
  934. // }
  935. // });
  936. // }
  937. // },
  938. // 数据库名称校验规则
  939. databaseNameValidator(rule, value, callback) {
  940. // 正则校验
  941. let regex = /^[a-z][a-z0-9]*$/
  942. if (regex.test(value)) {
  943. // callback(); // 输入内容符合规则
  944. } else {
  945. callback(new Error('只能包含小写字母和数字,且以小写字母开头'))
  946. }
  947. // 重名校验
  948. let isRepeat = this.databaseNameList.filter((item) => item == value)
  949. if (isRepeat.length !== 0) {
  950. callback(new Error('数据库名重复'))
  951. } else {
  952. callback()
  953. }
  954. },
  955. // 数据源类型改变回调
  956. dataSourceTypeChange(type) {
  957. this.$nextTick(() => {
  958. this.$refs.dataSourceForm.resetFields()
  959. this.dataSourceForm.databaseType = 'mysql'
  960. this.selecthandle('mysql')
  961. })
  962. },
  963. handleOpe() {
  964. },
  965. /** 查询租户信息列表 */
  966. getList() {
  967. this.loading = true
  968. this.currentPage = this.queryParams.pageNum
  969. listTenant(this.queryParams).then((response) => {
  970. this.tenantList = response.rows
  971. this.tenantList.forEach(item => {
  972. item['hasChildren'] = true
  973. })
  974. this.total = response.total
  975. this.loading = false
  976. })
  977. },
  978. // 取消按钮
  979. cancel() {
  980. this.open = false
  981. this.reset()
  982. },
  983. // 绑定数据源取消按钮
  984. cancel1() {
  985. this.dataSourceOpen = false
  986. this.reset1()
  987. },
  988. // 表单重置
  989. reset() {
  990. this.form = {
  991. tenantParentId: null,
  992. tenantId: null,
  993. tenantName: null,
  994. tenantCode: null,
  995. owner: null,
  996. contactInfo: null,
  997. address: null,
  998. createBy: null,
  999. createTime: null
  1000. }
  1001. this.resetForm('form')
  1002. },
  1003. // 表单重置
  1004. reset1() {
  1005. this.dataSourceType = true
  1006. this.dataSourceForm = {
  1007. id: null,
  1008. databaseName: null,
  1009. databaseIp: null,
  1010. tenantAccount: '',
  1011. username: null,
  1012. password: null,
  1013. portNumber: null,
  1014. databaseType: 'mysql'
  1015. }
  1016. // this.resetForm("dataSourceForm");
  1017. },
  1018. /** 搜索按钮操作 */
  1019. handleQuery() {
  1020. this.queryParams.pageNum = 1
  1021. this.getList()
  1022. },
  1023. /** 重置按钮操作 */
  1024. resetQuery() {
  1025. this.resetForm('queryForm')
  1026. this.handleQuery()
  1027. },
  1028. // 多选框选中数据
  1029. handleSelectionChange(selection) {
  1030. this.selection = selection
  1031. this.ids = selection.map((item) => item.tenantId)
  1032. this.single = selection.length !== 1
  1033. this.multiple = !selection.length
  1034. },
  1035. /** 新增按钮操作 */
  1036. handleAdd() {
  1037. this.getTenantAllList()
  1038. // this.reset();
  1039. this.open = true
  1040. this.title = '添加租户信息'
  1041. },
  1042. /** 修改按钮操作 */
  1043. handleUpdate(row) {
  1044. this.reset()
  1045. const tenantId = row.tenantId || this.ids
  1046. getTenant(tenantId).then((response) => {
  1047. this.form = response.data
  1048. this.open = true
  1049. this.title = '修改租户信息'
  1050. })
  1051. },
  1052. /** 绑定数据源按钮操作 */
  1053. bindDatasource(row) {
  1054. this.currentTenantInfo = row
  1055. this.reset1()
  1056. this.dialogLoading = false
  1057. this.dataSourceOpen = true
  1058. this.dataSourceTitle = row.tenantName + '配置数据库'
  1059. this.fromTenantId = row.tenantId
  1060. this.dataSourceTypeChange()
  1061. // const tenantId = row.tenantId || this.ids;
  1062. // getTenant(tenantId).then((response) => {
  1063. // this.form = response.data;
  1064. // this.open = true;
  1065. // this.title = "修改租户信息";
  1066. // });
  1067. },
  1068. /** 提交按钮 */
  1069. submitForm() {
  1070. if (this.form.tenantParentId.length >= 0) {
  1071. // 处理当前租户的上级租户id
  1072. this.form.tenantParentId = this.form.tenantParentId[this.form.tenantParentId.length - 1] != undefined ? this.form.tenantParentId[this.form.tenantParentId.length - 1] : ''
  1073. }
  1074. this.form.tenantClientLoginUrl = this.dict.type.system_login_url.find(item => item.label == 'client_login_url')?.value.replace("#{val}", this.form.tenantCode)
  1075. this.form.tenantToolLoginUrl = this.dict.type.system_login_url.find(item => item.label == 'crm_login_url')?.value.replace("#{val}", this.form.tenantCode)
  1076. this.$refs['form'].validate((valid) => {
  1077. if (valid) {
  1078. if (this.form.tenantId != null) {
  1079. updateTenant(this.form).then((response) => {
  1080. this.$modal.msgSuccess('修改成功')
  1081. this.open = false
  1082. this.getList()
  1083. })
  1084. } else {
  1085. addTenant(this.form).then((response) => {
  1086. this.$modal.msgSuccess('新增成功')
  1087. this.open = false
  1088. this.getList()
  1089. })
  1090. }
  1091. }
  1092. this.reset()
  1093. })
  1094. },
  1095. /** 提交按钮 */
  1096. submitForm1() {
  1097. if (this.dialogLoading) return
  1098. this.dialogLoading = true
  1099. this.$refs['dataSourceForm'].validate((valid) => {
  1100. if (valid) {
  1101. // const loading = servicesLoading(
  1102. // ".loadingClass",
  1103. // "正在绑定数据源",
  1104. // true
  1105. // );
  1106. if (this.dataSourceForm.id != null) {
  1107. // bindDatasource(this.dataSourceForm).then((response) => {
  1108. // this.$modal.msgSuccess("修改成功");
  1109. // this.dataSourceOpen = false;
  1110. // this.getList();
  1111. // });
  1112. this.dialogLoading = false
  1113. } else {
  1114. let query = {
  1115. tenantId: this.fromTenantId,
  1116. dataSource: this.dataSourceForm
  1117. }
  1118. bindDatasource(query)
  1119. .then((response) => {
  1120. if (response.code == 200) {
  1121. let data = {
  1122. userName: this.dataSourceForm.tenantAccount,
  1123. nickName: this.currentTenantInfo.tenantName,
  1124. userType: '01',
  1125. tenantId: this.currentTenantInfo.tenantId,
  1126. password: '123456'
  1127. }
  1128. createTenant(data)
  1129. .then(async (res) => {
  1130. if (res.code == 200) {
  1131. let resp = await initTenantMenuData(
  1132. this.currentTenantInfo.tenantId
  1133. )
  1134. if ((resp.code = 200)) {
  1135. this.$modal.msgSuccess('新增成功')
  1136. this.dataSourceOpen = false
  1137. this.getList()
  1138. }
  1139. }
  1140. })
  1141. .finally(() => {
  1142. this.dialogLoading = false
  1143. })
  1144. }
  1145. })
  1146. .finally(() => {
  1147. this.dialogLoading = false
  1148. })
  1149. }
  1150. }
  1151. })
  1152. },
  1153. /** 删除按钮操作 */
  1154. handleDelete(row) {
  1155. const tenantIds = row.tenantId || this.ids
  1156. this.$modal
  1157. .confirm('是否确认删除租户信息编号为"' + tenantIds + '"的数据项?')
  1158. .then(function () {
  1159. return delTenant(tenantIds)
  1160. })
  1161. .then(() => {
  1162. this.getList()
  1163. this.$modal.msgSuccess('删除成功')
  1164. })
  1165. .catch(() => {
  1166. })
  1167. },
  1168. /** 导出按钮操作 */
  1169. handleExport() {
  1170. this.download(
  1171. 'system/tenant/export',
  1172. {
  1173. ...this.queryParams
  1174. },
  1175. `tenant_${new Date().getTime()}.xlsx`
  1176. )
  1177. },
  1178. /**
  1179. * 选择数据源校验名称
  1180. */
  1181. selecthandle(row) {
  1182. let sql = {
  1183. sqlserver: 'sqlserver_connection_information',
  1184. mysql: 'mysql_connection_information',
  1185. dm: 'dm_connection_information',
  1186. oracle: 'oracle_connection_information'
  1187. }
  1188. let qar = {}
  1189. this.dict.type[sql[row]].forEach((item) => {
  1190. qar[item.label] = item.value
  1191. })
  1192. if (this.dataSourceType) {
  1193. let {databaseIp, password, portNumber, username} = qar
  1194. Object.assign(this.dataSourceForm, {
  1195. databaseIp,
  1196. password,
  1197. portNumber,
  1198. username
  1199. })
  1200. }
  1201. getDataSourceInfo(qar).then((res) => {
  1202. // console.log(res);
  1203. this.databaseNameList = res.data
  1204. })
  1205. },
  1206. handleTest() {
  1207. let formdata = {
  1208. databaseType: 'mysql',
  1209. databaseName: 'test1111',
  1210. databaseIp: '127.0.0.1',
  1211. username: 'testname',
  1212. password: '123123',
  1213. portNumber: '3306'
  1214. }
  1215. insertDataSource(formdata).then((res) => {
  1216. console.log(res)
  1217. })
  1218. },
  1219. //重置租户激活码表单
  1220. restTenantExpirationTime() {
  1221. this.tenantExpirationTimeFrom = {
  1222. tenantId: null,
  1223. tenantExpirationTime: ''
  1224. }
  1225. this.resetForm('tenantExpirationTimeFrom')
  1226. },
  1227. /**打开激活码弹窗*/
  1228. openTenantExpirationTime(row) {
  1229. // this.reset();
  1230. const tenantId = row.tenantId || this.ids
  1231. this.tenantExpirationTimeFrom.tenantId = row.tenantId
  1232. this.tenantExpirationTimeOpen = true
  1233. // this.title="激活租户";
  1234. },
  1235. /**激活租户操作*/
  1236. activationOperationMethod(form) {
  1237. this.$refs[form].validate(async (valid) => {
  1238. if (valid) {
  1239. let response = await activationOperation(
  1240. this.tenantExpirationTimeFrom
  1241. )
  1242. if (response.code == 200) {
  1243. this.$message.success('激活成功')
  1244. //重新刷新列表
  1245. this.getList()
  1246. } else {
  1247. this.$message.error('激活失败')
  1248. }
  1249. this.tenantExpirationTimeOpen = false
  1250. this.tenantExpirationTimeFrom = {
  1251. tenantId: null,
  1252. tenantExpirationTime: null
  1253. }
  1254. }
  1255. })
  1256. },
  1257. // 激活租户对话框取消按钮
  1258. tanentCancel() {
  1259. this.tenantExpirationTimeOpen = false
  1260. this.tenantExpirationTimeFrom = {
  1261. tenantId: null,
  1262. tenantExpirationTime: null
  1263. }
  1264. }
  1265. }
  1266. }
  1267. </script>