ScrmEndpointButton.vue 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. <!--add by chenguo 2025年7月31日
  2. 可用于不修改api/*.js 接口,实现前端代码复用
  3. 通过添加请求前缀的方式访问接口 如:/his/store/productList => [your-prefix]/his/store/productList
  4. 使用说明:引入组件并指定prefix及componentName(尽可能唯一)
  5. 添加组件方式:
  6. <smart-endpoint-toggle-button
  7. prefix="[your-prefix]"
  8. component-name="[your-component-name]">
  9. </smart-endpoint-toggle-button>
  10. 提供可用的回调
  11. @afterEndpoint="handleAfterEndpointToggle"
  12. @beforeEndpoint="handleBeforeEndpointToggle"
  13. -->
  14. <template>
  15. <div class="endpoint-toggle-container">
  16. <div class="toggle-switch" :class="{ 'new-endpoint': isUsingNewEndpoint }">
  17. <div class="toggle-option old-endpoint" @click="selectOldEndpoint">
  18. <span>旧接口</span>
  19. </div>
  20. <div class="toggle-option new-endpoint" @click="selectNewEndpoint">
  21. <span>新接口</span>
  22. </div>
  23. <div class="toggle-slider"></div>
  24. </div>
  25. </div>
  26. </template>
  27. <script>import {
  28. resetEndpoint, setActive,
  29. } from '@/utils/request'
  30. export default {
  31. name: 'ScrmEndpointButton',
  32. props: {
  33. //prefix:加在js请求前的方法
  34. prefix: {
  35. type: String,
  36. required: true
  37. },
  38. // 组件名称,用于生成唯一标识
  39. componentName: {
  40. type: String,
  41. required: true
  42. },
  43. // 默认选中状态(false表示默认选中旧接口,true表示默认选中新接口)
  44. defaultNewEndpoint: {
  45. type: Boolean,
  46. default: false
  47. }
  48. },
  49. data() {
  50. return {
  51. isUsingNewEndpoint: false,
  52. stateKey: ''
  53. }
  54. },
  55. created() {
  56. console.log('SmartEndpointToggleButton created');
  57. // 生成基于组件名和路由的唯一状态键
  58. this.stateKey = this.generateStateKey()
  59. // 初始化状态
  60. this.initializeState()
  61. },
  62. activated() {
  63. console.log('SmartEndpointToggleButton activated,stateKey='+this.stateKey+',prefix='+this.prefix+',is='+this.isUsingNewEndpoint);
  64. setActive(this.stateKey);
  65. // 页面激活时恢复状态
  66. this.restoreState()
  67. },
  68. deactivated() {
  69. console.log('SmartEndpointToggleButton deactivated');
  70. // 页面失活时保存状态
  71. this.saveState()
  72. },
  73. destroyed() {
  74. console.log('SmartEndpointToggleButton destroyed');
  75. // 组件销毁
  76. resetEndpoint(this.stateKey)
  77. },
  78. methods: {
  79. // 生成状态存储的唯一键
  80. generateStateKey() {
  81. const routePath = this.$route ? this.$route.path : ''
  82. const routeQuery = this.$route && this.$route.query ? JSON.stringify(this.$route.query) : ''
  83. return `endpoint_toggle_${this.componentName}_${routePath}_${routeQuery}`
  84. },
  85. // 初始化状态
  86. initializeState() {
  87. setActive(this.stateKey)
  88. // 默认选中旧接口
  89. this.isUsingNewEndpoint = this.defaultNewEndpoint
  90. this.saveState();
  91. },
  92. // 保存状态到 sessionStorage
  93. saveState() {
  94. try {
  95. const state = {
  96. prefix: this.prefix,
  97. isUsingNewEndpoint: this.isUsingNewEndpoint,
  98. timestamp: Date.now()
  99. }
  100. sessionStorage.setItem(this.stateKey, JSON.stringify(state))
  101. } catch (e) {
  102. console.warn('Failed to save endpoint toggle state:', e)
  103. }
  104. },
  105. // 从 sessionStorage 恢复状态
  106. restoreState() {
  107. try {
  108. const stateStr = sessionStorage.getItem(this.stateKey)
  109. if (stateStr) {
  110. const state = JSON.parse(stateStr)
  111. this.isUsingNewEndpoint = state.isUsingNewEndpoint || false
  112. } else {
  113. this.isUsingNewEndpoint = this.defaultNewEndpoint
  114. }
  115. } catch (e) {
  116. console.warn('Failed to restore endpoint toggle state:', e)
  117. this.isUsingNewEndpoint = this.defaultNewEndpoint
  118. }
  119. },
  120. // 选择旧接口
  121. selectOldEndpoint() {
  122. if (this.isUsingNewEndpoint) {
  123. this.toggleEndpointState(false)
  124. }
  125. },
  126. // 选择新接口
  127. selectNewEndpoint() {
  128. if (!this.isUsingNewEndpoint) {
  129. this.toggleEndpointState(true)
  130. }
  131. },
  132. // 切换端点状态
  133. async toggleEndpointState(newState) {
  134. // 触发切换前事件
  135. const beforeResult = this.$emit('beforeEndpoint', this.isUsingNewEndpoint)
  136. if (beforeResult === false) {
  137. return
  138. }
  139. try {
  140. // 更新状态
  141. this.isUsingNewEndpoint = newState
  142. // 保存状态
  143. this.saveState()
  144. // 触发切换后事件
  145. this.$emit('afterEndpoint', this.isUsingNewEndpoint)
  146. // 执行回调
  147. //if (this.$listeners.afterToggle) {
  148. // await this.$listeners.afterToggle(this.isUsingNewEndpoint)
  149. //}
  150. } catch (error) {
  151. console.error('Failed to toggle endpoint state:', error)
  152. // 发生错误时回滚状态
  153. this.isUsingNewEndpoint = !newState
  154. }
  155. }
  156. }
  157. }
  158. </script>
  159. <style scoped>.endpoint-toggle-container {
  160. display: inline-block;
  161. vertical-align: middle;
  162. }
  163. .toggle-switch {
  164. position: relative;
  165. display: flex;
  166. width: 145px;
  167. height: 32px;
  168. background-color: #f5f7fa;
  169. border-radius: 16px;
  170. cursor: pointer;
  171. overflow: hidden;
  172. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) inset;
  173. }
  174. .toggle-option {
  175. flex: 1;
  176. display: flex;
  177. align-items: center;
  178. justify-content: center;
  179. z-index: 2;
  180. transition: color 0.3s ease;
  181. font-size: 12px;
  182. font-weight: 500;
  183. }
  184. .toggle-option.old-endpoint {
  185. color: #ffffff;
  186. }
  187. .toggle-option.new-endpoint {
  188. color: #606266;
  189. }
  190. .toggle-switch.new-endpoint .toggle-option.old-endpoint {
  191. color: #606266;
  192. }
  193. .toggle-switch.new-endpoint .toggle-option.new-endpoint {
  194. color: #ffffff;
  195. }
  196. .toggle-slider {
  197. position: absolute;
  198. top: 2px;
  199. left: 2px;
  200. width: calc(50% - 2px);
  201. height: calc(100% - 4px);
  202. background-color: #3576f8;
  203. border-radius: 14px;
  204. transition: transform 0.3s ease;
  205. box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
  206. z-index: 1;
  207. }
  208. .toggle-switch.new-endpoint .toggle-slider {
  209. transform: translateX(100%);
  210. }
  211. /* 悬停效果 */
  212. .toggle-option:hover {
  213. opacity: 0.6;
  214. }
  215. </style>