|
@@ -0,0 +1,238 @@
|
|
|
+
|
|
|
+<!--add by chenguo 2025年7月31日
|
|
|
+ 可用于不修改api/*.js 接口,实现前端代码复用
|
|
|
+ 通过添加请求前缀的方式访问接口 如:/his/store/productList => [your-prefix]/his/store/productList
|
|
|
+ 使用说明:引入组件并指定prefix及componentName(尽可能唯一)
|
|
|
+ 添加组件方式:
|
|
|
+ <smart-endpoint-toggle-button
|
|
|
+ prefix="[your-prefix]"
|
|
|
+ component-name="[your-component-name]">
|
|
|
+ </smart-endpoint-toggle-button>
|
|
|
+ 提供可用的回调
|
|
|
+ @afterEndpoint="handleAfterEndpointToggle"
|
|
|
+ @beforeEndpoint="handleBeforeEndpointToggle"
|
|
|
+ -->
|
|
|
+<template>
|
|
|
+ <div class="endpoint-toggle-container">
|
|
|
+ <div class="toggle-switch" :class="{ 'new-endpoint': isUsingNewEndpoint }">
|
|
|
+ <div class="toggle-option old-endpoint" @click="selectOldEndpoint">
|
|
|
+ <span>旧接口</span>
|
|
|
+ </div>
|
|
|
+ <div class="toggle-option new-endpoint" @click="selectNewEndpoint">
|
|
|
+ <span>新接口</span>
|
|
|
+ </div>
|
|
|
+ <div class="toggle-slider"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>import {
|
|
|
+ resetEndpoint, setActive,
|
|
|
+} from '@/utils/request'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'ScrmEndpointButton',
|
|
|
+ props: {
|
|
|
+ //prefix:加在js请求前的方法
|
|
|
+ prefix: {
|
|
|
+ type: String,
|
|
|
+ required: true
|
|
|
+ },
|
|
|
+ // 组件名称,用于生成唯一标识
|
|
|
+ componentName: {
|
|
|
+ type: String,
|
|
|
+ required: true
|
|
|
+ },
|
|
|
+ // 默认选中状态(false表示默认选中旧接口,true表示默认选中新接口)
|
|
|
+ defaultNewEndpoint: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ isUsingNewEndpoint: false,
|
|
|
+ stateKey: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ console.log('SmartEndpointToggleButton created');
|
|
|
+ // 生成基于组件名和路由的唯一状态键
|
|
|
+ this.stateKey = this.generateStateKey()
|
|
|
+ // 初始化状态
|
|
|
+ this.initializeState()
|
|
|
+ },
|
|
|
+ activated() {
|
|
|
+ console.log('SmartEndpointToggleButton activated,stateKey='+this.stateKey+',prefix='+this.prefix+',is='+this.isUsingNewEndpoint);
|
|
|
+ setActive(this.stateKey);
|
|
|
+ // 页面激活时恢复状态
|
|
|
+ this.restoreState()
|
|
|
+ },
|
|
|
+ deactivated() {
|
|
|
+ console.log('SmartEndpointToggleButton deactivated');
|
|
|
+ // 页面失活时保存状态
|
|
|
+ this.saveState()
|
|
|
+ },
|
|
|
+ destroyed() {
|
|
|
+ console.log('SmartEndpointToggleButton destroyed');
|
|
|
+ // 组件销毁
|
|
|
+ resetEndpoint(this.stateKey)
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 生成状态存储的唯一键
|
|
|
+ generateStateKey() {
|
|
|
+ const routePath = this.$route ? this.$route.path : ''
|
|
|
+ const routeQuery = this.$route && this.$route.query ? JSON.stringify(this.$route.query) : ''
|
|
|
+ return `endpoint_toggle_${this.componentName}_${routePath}_${routeQuery}`
|
|
|
+ },
|
|
|
+
|
|
|
+ // 初始化状态
|
|
|
+ initializeState() {
|
|
|
+ setActive(this.stateKey)
|
|
|
+ // 默认选中旧接口
|
|
|
+ this.isUsingNewEndpoint = this.defaultNewEndpoint
|
|
|
+ this.saveState();
|
|
|
+ },
|
|
|
+
|
|
|
+ // 保存状态到 sessionStorage
|
|
|
+ saveState() {
|
|
|
+ try {
|
|
|
+ const state = {
|
|
|
+ prefix: this.prefix,
|
|
|
+ isUsingNewEndpoint: this.isUsingNewEndpoint,
|
|
|
+ timestamp: Date.now()
|
|
|
+ }
|
|
|
+ sessionStorage.setItem(this.stateKey, JSON.stringify(state))
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('Failed to save endpoint toggle state:', e)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 从 sessionStorage 恢复状态
|
|
|
+ restoreState() {
|
|
|
+ try {
|
|
|
+ const stateStr = sessionStorage.getItem(this.stateKey)
|
|
|
+ if (stateStr) {
|
|
|
+ const state = JSON.parse(stateStr)
|
|
|
+ this.isUsingNewEndpoint = state.isUsingNewEndpoint || false
|
|
|
+ } else {
|
|
|
+ this.isUsingNewEndpoint = this.defaultNewEndpoint
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.warn('Failed to restore endpoint toggle state:', e)
|
|
|
+ this.isUsingNewEndpoint = this.defaultNewEndpoint
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 选择旧接口
|
|
|
+ selectOldEndpoint() {
|
|
|
+ if (this.isUsingNewEndpoint) {
|
|
|
+ this.toggleEndpointState(false)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 选择新接口
|
|
|
+ selectNewEndpoint() {
|
|
|
+ if (!this.isUsingNewEndpoint) {
|
|
|
+ this.toggleEndpointState(true)
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 切换端点状态
|
|
|
+ async toggleEndpointState(newState) {
|
|
|
+ // 触发切换前事件
|
|
|
+ const beforeResult = this.$emit('beforeEndpoint', this.isUsingNewEndpoint)
|
|
|
+ if (beforeResult === false) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 更新状态
|
|
|
+ this.isUsingNewEndpoint = newState
|
|
|
+
|
|
|
+ // 保存状态
|
|
|
+ this.saveState()
|
|
|
+
|
|
|
+ // 触发切换后事件
|
|
|
+ this.$emit('afterEndpoint', this.isUsingNewEndpoint)
|
|
|
+
|
|
|
+ // 执行回调
|
|
|
+ //if (this.$listeners.afterToggle) {
|
|
|
+ // await this.$listeners.afterToggle(this.isUsingNewEndpoint)
|
|
|
+ //}
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Failed to toggle endpoint state:', error)
|
|
|
+ // 发生错误时回滚状态
|
|
|
+ this.isUsingNewEndpoint = !newState
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>.endpoint-toggle-container {
|
|
|
+ display: inline-block;
|
|
|
+ vertical-align: middle;
|
|
|
+}
|
|
|
+
|
|
|
+.toggle-switch {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ width: 145px;
|
|
|
+ height: 32px;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border-radius: 16px;
|
|
|
+ cursor: pointer;
|
|
|
+ overflow: hidden;
|
|
|
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) inset;
|
|
|
+}
|
|
|
+
|
|
|
+.toggle-option {
|
|
|
+ flex: 1;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ z-index: 2;
|
|
|
+ transition: color 0.3s ease;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+
|
|
|
+.toggle-option.old-endpoint {
|
|
|
+ color: #ffffff;
|
|
|
+}
|
|
|
+
|
|
|
+.toggle-option.new-endpoint {
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+
|
|
|
+.toggle-switch.new-endpoint .toggle-option.old-endpoint {
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+
|
|
|
+.toggle-switch.new-endpoint .toggle-option.new-endpoint {
|
|
|
+ color: #ffffff;
|
|
|
+}
|
|
|
+
|
|
|
+.toggle-slider {
|
|
|
+ position: absolute;
|
|
|
+ top: 2px;
|
|
|
+ left: 2px;
|
|
|
+ width: calc(50% - 2px);
|
|
|
+ height: calc(100% - 4px);
|
|
|
+ background-color: #3576f8;
|
|
|
+ border-radius: 14px;
|
|
|
+ transition: transform 0.3s ease;
|
|
|
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
|
+ z-index: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.toggle-switch.new-endpoint .toggle-slider {
|
|
|
+ transform: translateX(100%);
|
|
|
+}
|
|
|
+
|
|
|
+/* 悬停效果 */
|
|
|
+.toggle-option:hover {
|
|
|
+ opacity: 0.6;
|
|
|
+}
|
|
|
+</style>
|