JThirdAppButton.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <template>
  2. <template v-if="syncToApp || syncToLocal">
  3. <JThirdAppDropdown v-if="enabledTypes.wechatEnterprise" type="wechatEnterprise" name="企微" v-bind="bindAttrs" v-on="bindEvents" />
  4. <JThirdAppDropdown v-if="enabledTypes.dingtalk" type="dingtalk" name="钉钉" v-bind="bindAttrs" v-on="bindEvents" />
  5. </template>
  6. <template v-else>未设置任何同步方向</template>
  7. </template>
  8. <script lang="ts" setup>
  9. import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
  10. import { ref, computed, createVNode, h, resolveComponent } from 'vue';
  11. import { defHttp } from '/@/utils/http/axios';
  12. import { backEndUrl, getEnabledTypes, doSyncThirdApp } from './jThirdApp.api';
  13. import { Modal, Input } from 'ant-design-vue';
  14. import JThirdAppDropdown from './JThirdAppDropdown.vue';
  15. import { useMessage } from '/@/hooks/web/useMessage';
  16. const { createMessage, createWarningModal } = useMessage();
  17. const props = defineProps({
  18. // 同步类型,可以是 user、depart
  19. bizType: {
  20. type: String,
  21. required: true,
  22. },
  23. // 是否允许同步到第三方APP
  24. syncToApp: Boolean,
  25. // 是否允许第三方APP同步到本地
  26. syncToLocal: Boolean,
  27. // 选择的行
  28. selectedRowKeys: Array,
  29. });
  30. // 声明Emits
  31. const emit = defineEmits(['sync-ok', 'sync-error', 'sync-finally']);
  32. const enabledTypes = ref({});
  33. // 绑定属性
  34. const bindAttrs = computed(() => {
  35. return {
  36. syncToApp: props.syncToApp,
  37. syncToLocal: props.syncToLocal,
  38. };
  39. });
  40. // 绑定方法
  41. const bindEvents = computed(() => {
  42. return {
  43. 'to-app': onToApp,
  44. 'to-local': onToLocal,
  45. };
  46. });
  47. // 同步到第三方App
  48. function onToApp(e) {
  49. doSync(e.type, '/toApp');
  50. }
  51. // 同步到本地
  52. function onToLocal(e) {
  53. doSync(e.type, '/toLocal');
  54. }
  55. // 获取启用的第三方App
  56. async function loadEnabledTypes() {
  57. enabledTypes.value = await getEnabledTypes();
  58. }
  59. // 开始同步第三方App
  60. function doSync(type, direction) {
  61. let urls = backEndUrl[type];
  62. if (!(urls && urls[props.bizType])) {
  63. console.warn('配置出错');
  64. return;
  65. }
  66. let url = urls[props.bizType] + direction;
  67. let selectedRowKeys = props.selectedRowKeys;
  68. let content = '确定要开始同步全部数据吗?可能花费较长时间!';
  69. if (Array.isArray(selectedRowKeys) && selectedRowKeys.length > 0) {
  70. content = `确定要开始同步这 ${selectedRowKeys.length} 项吗?`;
  71. } else {
  72. selectedRowKeys = [];
  73. }
  74. return new Promise((resolve, reject) => {
  75. const model = Modal.confirm({
  76. icon: createVNode(ExclamationCircleOutlined),
  77. title: '同步',
  78. content,
  79. onOk: () => {
  80. model.update({
  81. keyboard: false,
  82. okText: '同步中…',
  83. cancelButtonProps: { disabled: true },
  84. });
  85. let params = { ids: selectedRowKeys.join(',') };
  86. return defHttp
  87. .get({ url, params }, { isTransformResponse: false })
  88. .then((res) => {
  89. let options = {};
  90. if (res.result) {
  91. options = {
  92. width: 600,
  93. title: res.message,
  94. content: () => {
  95. let nodes;
  96. let successInfo = [`成功信息如下:`, renderTextarea(h, res.result.successInfo.map((v, i) => `${i + 1}. ${v}`).join('\n'))];
  97. if (res.success) {
  98. nodes = [...successInfo, h('br'), `无失败信息!`];
  99. } else {
  100. nodes = [
  101. `失败信息如下:`,
  102. renderTextarea(h, res.result.failInfo.map((v, i) => `${i + 1}. ${v}`).join('\n')),
  103. h('br'),
  104. ...successInfo,
  105. ];
  106. }
  107. return nodes;
  108. },
  109. };
  110. }
  111. if (res.success) {
  112. if (options != null) {
  113. Modal.success(options);
  114. } else {
  115. createMessage.warning(res.message);
  116. }
  117. emit('sync-ok');
  118. } else {
  119. if (options != null) {
  120. Modal.warning(options);
  121. } else {
  122. createMessage.warning(res.message);
  123. }
  124. emit('sync-error');
  125. }
  126. })
  127. .catch(() => model.destroy())
  128. .finally(() => {
  129. resolve();
  130. emit('sync-finally', {
  131. type,
  132. direction,
  133. isToApp: direction === '/toApp',
  134. isToLocal: direction === '/toLocal',
  135. });
  136. });
  137. },
  138. onCancel() {
  139. resolve();
  140. },
  141. });
  142. });
  143. }
  144. function renderTextarea(h, value) {
  145. return h(
  146. 'div',
  147. {
  148. id: 'box',
  149. style: {
  150. minHeight: '100px',
  151. border: '1px solid #d9d9d9',
  152. fontSize: '14px',
  153. maxHeight: '250px',
  154. whiteSpace: 'pre',
  155. overflow: 'auto',
  156. padding: '10px',
  157. },
  158. },
  159. value
  160. );
  161. }
  162. // 获取启用的第三方App
  163. loadEnabledTypes();
  164. </script>
  165. <style scoped>
  166. #box:hover {
  167. border-color: #40a9ff;
  168. }
  169. </style>