NodeMergeDialog.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <template>
  2. <el-dialog
  3. v-model="visible"
  4. width="650"
  5. :before-close="handleClose"
  6. >
  7. <el-form :model="formData" :rules="formRules">
  8. <el-row class="data-category">{{message}}</el-row>
  9. <el-row>
  10. <el-input maxlength="64" show-word-limit v-model="formData.search"></el-input><el-button @click="handleSearch">搜索</el-button></el-row>
  11. <!-- <el-row>
  12. <el-form-item prop="linkDirection">
  13. <el-radio v-model="formData.linkDirection" label="1">被融合(选择节点被替换)</el-radio>
  14. <el-radio v-model="formData.linkDirection" label="2">融合(当前节点被替换)</el-radio>
  15. </el-form-item>
  16. </el-row> -->
  17. <el-row class="props-content">
  18. <el-checkbox :indeterminate="formData.isIndeterminate" v-model="formData.checkAll" @change="handleCheckAllChange">全选</el-checkbox>
  19. <div style="margin: 15px 0;"></div>
  20. <el-form-item prop="selectedNodes">
  21. <el-checkbox-group v-model="formData.selectedNodes" class="checkbox-content" >
  22. <el-checkbox style="width:220px" v-for="item in formData.nodes" :value="item.id" :key="item.id">{{item.name}}({{item.category}})</el-checkbox>
  23. </el-checkbox-group>
  24. </el-form-item>
  25. </el-row>
  26. </el-form>
  27. <template #footer>
  28. <span class="dialog-footer">
  29. <el-button @click="handleCancel">取 消</el-button>
  30. <el-button type="primary" @click="handleConfirm">保 存</el-button>
  31. </span>
  32. </template>
  33. </el-dialog>
  34. </template>
  35. <script setup lang="ts">
  36. import { ref, watch, toRefs, onMounted} from 'vue';
  37. import r from '@/utils/request.ts';
  38. import { ElMessageBox, ElNotification } from 'element-plus';
  39. /**********emits**********/
  40. const emit = defineEmits(['update:modelValue', 'confirm', 'cancel','server-saved']);
  41. /**********props**********/
  42. const props = defineProps({
  43. modelValue: {
  44. type: Boolean,
  45. default: false
  46. },
  47. title: {
  48. type: String,
  49. default: '确认操作'
  50. },
  51. data: {
  52. type: Object,
  53. default: {},
  54. },
  55. nodes: {
  56. type: Object,
  57. default: {},
  58. },
  59. message: {
  60. type: String,
  61. default: '您确定要执行此操作吗?'
  62. },
  63. });
  64. /**********props_watch**********/
  65. watch(() => props.modelValue, (newValue) => {
  66. console.log("watch modelValue");
  67. visible.value = newValue;
  68. });
  69. watch(()=>props.data,(newvalue, oldvalue)=>{
  70. console.log("watch data");
  71. formData.value.name = '';
  72. formData.value.id = 0;
  73. formData.value.category = newvalue.category;
  74. formData.value.name = newvalue.name;
  75. formData.value.selectedNodes = [];
  76. });
  77. watch(()=>props.nodes,(newvalue, oldvalue)=>{
  78. console.log("watch nodes");
  79. formData.value.nodes = newvalue;
  80. });
  81. const handleClose = (done) => {
  82. emit('update:modelValue', false);
  83. done();
  84. };
  85. /**********ui_data**********/
  86. const visible = ref(props.modelValue);
  87. const formData = ref({
  88. id: 0,
  89. category: "",
  90. name: "",
  91. status: 0,
  92. search: "",
  93. nodes: [],
  94. linkDirection: "2",
  95. checkAll: false,
  96. isIndeterminate: true,
  97. selectedNodes: []
  98. });
  99. const formRules = ref({
  100. linkType: [{required: true, message:"链接类型必须选择", trigger:"blur"}],
  101. });
  102. /**********ui_handler**********/
  103. function handleCheckAllChange(val) {
  104. formData.value.selectedNodes = val ? props.nodes.map((data,index)=>{ return data.id;}) : [];
  105. formData.value.isIndeterminate = false;
  106. };
  107. function handleCheckedCitiesChange(value) {
  108. let checkedCount = value.length;
  109. this.checkAll = checkedCount === data.nodes.length;
  110. this.isIndeterminate = checkedCount > 0 && checkedCount < data.nodes.length;
  111. }
  112. const handleSearch = () =>{
  113. const response = r.request<string[]>({
  114. url: "/api/nodes/search/"+formData.value.search+"/0/1",
  115. method: "get"
  116. });
  117. response.then(result => {
  118. formData.value.nodes = result["nodes"];
  119. });
  120. }
  121. const handleConfirm = () => {
  122. var targetValidate = false;
  123. if (formData.value.linkDirection == "2" ){
  124. //替换候选的对象,可以替换多个
  125. if (formData.value.selectedNodes.length > 0){
  126. targetValidate = true;
  127. }
  128. }
  129. if (formData.value.linkDirection == "1" ){
  130. //被候选对象替换,仅允许被1个替换
  131. if (formData.value.selectedNodes.length == 1 ){
  132. targetValidate = true;
  133. }
  134. }
  135. if (targetValidate == false){
  136. ElMessageBox.alert(
  137. '替换模式下,至少需要选择一个目标;被替换模式下,仅可以选择一个目标',
  138. '警告',
  139. {
  140. confirmButtonText: '确定',
  141. callback: action => {
  142. console.log(action)
  143. }
  144. }
  145. );
  146. return;
  147. }
  148. var requestData = [];
  149. var mergeData = {
  150. src_id: 0,
  151. dest_id: 0,
  152. }
  153. formData.value.selectedNodes.forEach((value)=>{
  154. mergeData.src_id = props.data.id;
  155. mergeData.dest_id = value;
  156. if (formData.value.linkDirection == "1"){
  157. mergeData.dest_id = props.data.id;
  158. mergeData.src_id = value;
  159. }
  160. requestData.push({...mergeData})
  161. });
  162. const response = r.request<string[]>({
  163. url: "/api/node-merge",
  164. method: "post",
  165. data: requestData,
  166. });
  167. response.then(result => {
  168. if (result.error_code == 0){
  169. ElNotification({
  170. title: '成功',
  171. message: '链接已经成功创建了',
  172. type: 'success'
  173. });
  174. emit('server-saved', result.edges);
  175. emit('created');
  176. } else {
  177. ElNotification({
  178. title: '失败',
  179. message: '链接创建失败 '+ result.error_msg,
  180. type: 'error'
  181. });
  182. }
  183. emit('update:modelValue', false);
  184. });
  185. };
  186. const handleCancel = () => {
  187. emit('cancel');
  188. emit('update:modelValue', false);
  189. visible.value = false;
  190. };
  191. /**********vue_event_handler**********/
  192. onMounted( ()=>{
  193. });
  194. /**********vue_export_def**********/
  195. const openDialog = ()=>{
  196. //visible.value = true;
  197. }
  198. defineExpose({openDialog});
  199. </script>
  200. <style scoped>
  201. .data-category{
  202. width: 600px;
  203. font-size: 18pt;
  204. color:rgb(3, 57, 123);
  205. font-weight: 800;
  206. justify-content: center;
  207. margin-bottom: 10px;
  208. }
  209. .data-name{
  210. margin: 5px;
  211. display: flex;
  212. flex-direction: column;
  213. width: 580px;
  214. }
  215. .props-content{
  216. width: 100%;
  217. height: 100%;
  218. display: flex;
  219. justify-content: flex-start;
  220. overflow-y: auto;
  221. }
  222. .checkbox-content{
  223. width: 600px;
  224. height: 300px;
  225. display: flex;
  226. flex-direction: row;
  227. flex-wrap: wrap;
  228. justify-content: flex-start;
  229. overflow-y: auto;
  230. }
  231. .data-prop{
  232. margin: 5px;
  233. width: 600px;
  234. display: flex;
  235. flex-direction: column;
  236. }
  237. .prop-name{
  238. background-color: #efefef;
  239. color:rgb(11, 117, 247);
  240. width:580px;
  241. }
  242. .data-text{
  243. width: 580px;
  244. background-color: #efefef;
  245. }
  246. </style>