xray_rule_modal.html 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. {{define "modals/ruleModal"}}
  2. <a-modal id="rule-modal" v-model="ruleModal.visible" :title="ruleModal.title" @ok="ruleModal.ok" :confirm-loading="ruleModal.confirmLoading" :closable="true" :mask-closable="false" :ok-text="ruleModal.okText" cancel-text='{{ i18n "close" }}' :class="themeSwitcher.currentTheme">
  3. <a-form :colon="false" :label-col="{ md: {span:8} }" :wrapper-col="{ md: {span:14} }">
  4. <a-form-item>
  5. <template slot="label">
  6. <a-tooltip>
  7. <template slot="title">
  8. <span>{{ i18n "pages.xray.rules.useComma" }}</span>
  9. </template> Source IPs <a-icon type="question-circle"></a-icon>
  10. </a-tooltip>
  11. </template>
  12. <a-input v-model.trim="ruleModal.rule.sourceIP"></a-input>
  13. </a-form-item>
  14. <a-form-item>
  15. <template slot="label">
  16. <a-tooltip>
  17. <template slot="title">
  18. <span>{{ i18n "pages.xray.rules.useComma" }}</span>
  19. </template> Source Port <a-icon type="question-circle"></a-icon>
  20. </a-tooltip>
  21. </template>
  22. <a-input v-model.trim="ruleModal.rule.sourcePort"></a-input>
  23. </a-form-item>
  24. <a-form-item label='Network'>
  25. <a-select v-model="ruleModal.rule.network" :dropdown-class-name="themeSwitcher.currentTheme">
  26. <a-select-option v-for="x in ['','TCP','UDP','TCP,UDP']" :value="x">[[ x ]]</a-select-option>
  27. </a-select>
  28. </a-form-item>
  29. <a-form-item label='Protocol'>
  30. <a-select v-model="ruleModal.rule.protocol" mode="multiple" :dropdown-class-name="themeSwitcher.currentTheme">
  31. <a-select-option v-for="x in ['http','tls','bittorrent','quic']" :value="x">[[ x ]]</a-select-option>
  32. </a-select>
  33. </a-form-item>
  34. <a-form-item label='Attributes'>
  35. <a-button icon="plus" size="small" :style="{ marginLeft: '10px' }" @click="ruleModal.rule.attrs.push(['', ''])"></a-button>
  36. </a-form-item>
  37. <a-form-item :wrapper-col="{span: 24}">
  38. <a-input-group compact v-for="(attr,index) in ruleModal.rule.attrs">
  39. <a-input :style="{ width: '50%' }" v-model="attr[0]" placeholder='{{ i18n "pages.inbounds.stream.general.name" }}'>
  40. <template slot="addonBefore" :style="{ margin: '0' }">[[ index+1 ]]</template>
  41. </a-input>
  42. <a-input :style="{ width: '50%' }" v-model="attr[1]" placeholder='{{ i18n "pages.inbounds.stream.general.value" }}'>
  43. <a-button icon="minus" slot="addonAfter" size="small" @click="ruleModal.rule.attrs.splice(index,1)"></a-button>
  44. </a-input>
  45. </a-input-group>
  46. </a-form-item>
  47. <a-form-item>
  48. <template slot="label">
  49. <a-tooltip>
  50. <template slot="title">
  51. <span>{{ i18n "pages.xray.rules.useComma" }}</span>
  52. </template> IP <a-icon type="question-circle"></a-icon>
  53. </a-tooltip>
  54. </template>
  55. <a-input v-model.trim="ruleModal.rule.ip"></a-input>
  56. </a-form-item>
  57. <a-form-item>
  58. <template slot="label">
  59. <a-tooltip>
  60. <template slot="title">
  61. <span>{{ i18n "pages.xray.rules.useComma" }}</span>
  62. </template> Domain <a-icon type="question-circle"></a-icon>
  63. </a-tooltip>
  64. </template>
  65. <a-input v-model.trim="ruleModal.rule.domain"></a-input>
  66. </a-form-item>
  67. <a-form-item>
  68. <template slot="label">
  69. <a-tooltip>
  70. <template slot="title">
  71. <span>{{ i18n "pages.xray.rules.useComma" }}</span>
  72. </template> User <a-icon type="question-circle"></a-icon>
  73. </a-tooltip>
  74. </template>
  75. <a-input v-model.trim="ruleModal.rule.user"></a-input>
  76. </a-form-item>
  77. <a-form-item>
  78. <template slot="label">
  79. <a-tooltip>
  80. <template slot="title">
  81. <span>{{ i18n "pages.xray.rules.useComma" }}</span>
  82. </template> Port <a-icon type="question-circle"></a-icon>
  83. </a-tooltip>
  84. </template>
  85. <a-input v-model.trim="ruleModal.rule.port"></a-input>
  86. </a-form-item>
  87. <a-form-item label='Inbound Tags'>
  88. <a-select v-model="ruleModal.rule.inboundTag" mode="multiple" :dropdown-class-name="themeSwitcher.currentTheme">
  89. <a-select-option v-for="tag in ruleModal.inboundTags" :value="tag">[[ tag ]]</a-select-option>
  90. </a-select>
  91. </a-form-item>
  92. <a-form-item label='Outbound Tag'>
  93. <a-select v-model="ruleModal.rule.outboundTag" :dropdown-class-name="themeSwitcher.currentTheme">
  94. <a-select-option v-for="tag in ruleModal.outboundTags" :value="tag">[[ tag ]]</a-select-option>
  95. </a-select>
  96. </a-form-item>
  97. <a-form-item>
  98. <template slot="label">
  99. <a-tooltip>
  100. <template slot="title">
  101. <span>{{ i18n "pages.xray.balancer.balancerDesc" }}</span>
  102. </template> Balancer Tag <a-icon type="question-circle"></a-icon>
  103. </a-tooltip>
  104. </template>
  105. <a-select v-model="ruleModal.rule.balancerTag" :dropdown-class-name="themeSwitcher.currentTheme">
  106. <a-select-option v-for="tag in ruleModal.balancerTags" :value="tag">[[ tag ]]</a-select-option>
  107. </a-select>
  108. </a-form-item>
  109. </a-form>
  110. </a-modal>
  111. <script>
  112. const ruleModal = {
  113. title: '',
  114. visible: false,
  115. confirmLoading: false,
  116. okText: '{{ i18n "sure" }}',
  117. isEdit: false,
  118. confirm: null,
  119. rule: {
  120. type: "field",
  121. domain: "",
  122. ip: "",
  123. port: "",
  124. sourcePort: "",
  125. network: "",
  126. sourceIP: "",
  127. user: "",
  128. inboundTag: [],
  129. protocol: [],
  130. attrs: [],
  131. outboundTag: "",
  132. balancerTag: "",
  133. },
  134. inboundTags: [],
  135. outboundTags: [],
  136. users: [],
  137. balancerTags: [],
  138. ok() {
  139. newRule = ruleModal.getResult();
  140. ObjectUtil.execute(ruleModal.confirm, newRule);
  141. },
  142. show({
  143. title = '',
  144. okText = '{{ i18n "sure" }}',
  145. rule,
  146. confirm = (rule) => {},
  147. isEdit = false
  148. }) {
  149. this.title = title;
  150. this.okText = okText;
  151. this.confirm = confirm;
  152. this.visible = true;
  153. if (isEdit) {
  154. this.rule.domain = rule.domain ? rule.domain.join(',') : [];
  155. this.rule.ip = rule.ip ? rule.ip.join(',') : [];
  156. this.rule.port = rule.port;
  157. this.rule.sourcePort = rule.sourcePort;
  158. this.rule.network = rule.network;
  159. this.rule.sourceIP = rule.sourceIP ? rule.sourceIP.join(',') : [];
  160. this.rule.user = rule.user ? rule.user.join(',') : [];
  161. this.rule.inboundTag = rule.inboundTag;
  162. this.rule.protocol = rule.protocol;
  163. this.rule.attrs = rule.attrs ? Object.entries(rule.attrs) : [];
  164. this.rule.outboundTag = rule.outboundTag;
  165. this.rule.balancerTag = rule.balancerTag ? rule.balancerTag : "";
  166. } else {
  167. this.rule = {
  168. domain: "",
  169. ip: "",
  170. port: "",
  171. sourcePort: "",
  172. network: "",
  173. sourceIP: "",
  174. user: "",
  175. inboundTag: [],
  176. protocol: [],
  177. attrs: [],
  178. outboundTag: "",
  179. balancerTag: "",
  180. }
  181. }
  182. this.isEdit = isEdit;
  183. this.inboundTags = app.templateSettings.inbounds.filter((i) => !ObjectUtil.isEmpty(i.tag)).map(obj => obj.tag);
  184. this.inboundTags.push(...app.inboundTags);
  185. if (app.enableDNS && !ObjectUtil.isEmpty(app.dnsTag)) this.inboundTags.push(app.dnsTag)
  186. this.outboundTags = ["", ...app.templateSettings.outbounds.filter((o) => !ObjectUtil.isEmpty(o.tag)).map(obj => obj.tag)];
  187. if (app.templateSettings.reverse) {
  188. if (app.templateSettings.reverse.bridges) {
  189. this.inboundTags.push(...app.templateSettings.reverse.bridges.map(b => b.tag));
  190. }
  191. if (app.templateSettings.reverse.portals) this.outboundTags.push(...app.templateSettings.reverse.portals.map(b => b.tag));
  192. }
  193. if (app.templateSettings.routing && app.templateSettings.routing.balancers) {
  194. this.balancerTags = ["", ...app.templateSettings.routing.balancers.filter((o) => !ObjectUtil.isEmpty(o.tag)).map(obj => obj.tag)];
  195. }
  196. },
  197. close() {
  198. ruleModal.visible = false;
  199. ruleModal.loading(false);
  200. },
  201. loading(loading = true) {
  202. ruleModal.confirmLoading = loading;
  203. },
  204. getResult() {
  205. value = ruleModal.rule;
  206. rule = {};
  207. newRule = {};
  208. rule.type = "field";
  209. rule.domain = value.domain.length > 0 ? value.domain.split(',') : [];
  210. rule.ip = value.ip.length > 0 ? value.ip.split(',') : [];
  211. rule.port = value.port;
  212. rule.sourcePort = value.sourcePort;
  213. rule.network = value.network;
  214. rule.sourceIP = value.sourceIP.length > 0 ? value.sourceIP.split(',') : [];
  215. rule.user = value.user.length > 0 ? value.user.split(',') : [];
  216. rule.inboundTag = value.inboundTag;
  217. rule.protocol = value.protocol;
  218. rule.attrs = Object.fromEntries(value.attrs);
  219. rule.outboundTag = value.outboundTag == "" ? undefined : value.outboundTag;
  220. rule.balancerTag = value.balancerTag == "" ? undefined : value.balancerTag;
  221. for (const [key, value] of Object.entries(rule)) {
  222. if (value !== null && value !== undefined && !(Array.isArray(value) && value.length === 0) && !(typeof value === 'object' && Object.keys(value).length === 0) && value !== '') {
  223. newRule[key] = value;
  224. }
  225. }
  226. return newRule;
  227. }
  228. };
  229. new Vue({
  230. delimiters: ['[[', ']]'],
  231. el: '#rule-modal',
  232. data: {
  233. ruleModal: ruleModal,
  234. }
  235. });
  236. </script>
  237. {{end}}