NodeLinkDialog.vue 7.6 KB

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