Browse Source

代码获取模块 图片动态获取

master
[yxf] 1 month ago
parent
commit
3560049823
  1. 44
      im-admin-ui/src/views/im/code/components/alink.vue
  2. 52
      im-admin-ui/src/views/im/code/components/wangye.vue
  3. 64
      im-admin-ui/src/views/im/code/index.vue
  4. 25
      im-admin/ruoyi-im/src/main/java/org/dromara/im/controller/ImAgentController.java
  5. 9
      im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/ImAgent.java
  6. 8
      im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/bo/ImAgentBo.java
  7. 9
      im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/vo/ImAgentVo.java
  8. 5
      im-admin/ruoyi-im/src/main/java/org/dromara/im/service/IImAgentService.java
  9. 14
      im-admin/ruoyi-im/src/main/java/org/dromara/im/service/impl/ImAgentServiceImpl.java

44
im-admin-ui/src/views/im/code/components/alink.vue

@ -11,27 +11,21 @@
</template> </template>
<script> <script>
import { getInfo } from '@/api/login';
export default { export default {
name: 'Alink', name: 'Alink',
props: { props: {
tokeninfo: {}, tokeninfo: {},
siteUrl: '' siteUrl: String,
}, // uniqueToken
uniqueToken: String
data() {
return {
uniqueToken: '',
loading: false
};
}, },
computed: { computed: {
linkUrl3() { linkUrl3() {
const baseUrl = `${location.origin}/h5`; const baseUrl = `${location.origin}/h5`;
// token
if (this.uniqueToken) { if (this.uniqueToken) {
return `${baseUrl}?token=${this.uniqueToken}`; return `${baseUrl}?token=${this.uniqueToken}`;
} }
@ -39,34 +33,10 @@ export default {
return baseUrl; return baseUrl;
} }
}, },
mounted() {
this.fetchUserInfo();
},
methods: { methods: {
//
async fetchUserInfo() {
this.loading = true;
try {
const res = await getInfo();
// tokenInfo
if (res.data && res.data.tokenInfo) {
this.uniqueToken = res.data.tokenInfo.uniqueToken || '';
}
} catch (error) {
// props
if (this.tokeninfo && typeof this.tokeninfo === 'object') {
this.uniqueToken = this.tokeninfo.uniqueToken || '';
}
} finally {
this.loading = false;
}
},
getCopy(id) { getCopy(id) {
this.$emit('cgetCopy', id); this.$emit('cget-copy', id);
} }
} }
}; };

52
im-admin-ui/src/views/im/code/components/wangye.vue

@ -2,7 +2,8 @@
<div class="content"> <div class="content">
<p class="font-w">使用简介</p> <p class="font-w">使用简介</p>
<p class="text-i">网页内快速接入客服让网页拥有客服窗口请把一下代码复制到网页最底部</p> <p class="text-i">网页内快速接入客服让网页拥有客服窗口请把一下代码复制到网页最底部</p>
<Divider /> <el-divider />
<p class="typetitle">获取代码</p> <p class="typetitle">获取代码</p>
<div class="fenlei"> <div class="fenlei">
@ -17,10 +18,10 @@
"authInit":true, "authInit":true,
openUrl: '{{ siteUrl }}', openUrl: '{{ siteUrl }}',
token: '{{ uniqueToken }}', token: '{{ uniqueToken }}',
isShowTip: true, // false,true isShowTip: true,
mobileIcon: '', // mobileIcon: '{{ floatConfig?.mobileImage || "" }}',
pcIcon: '', // pc pcIcon: '{{ floatConfig?.pcImage || "" }}',
windowStyle:'',// center windowStyle:'',
}; };
var canCustomerServer = new initCustomerServer(option); var canCustomerServer = new initCustomerServer(option);
canCustomerServer.init(); canCustomerServer.init();
@ -28,8 +29,8 @@
document.head.appendChild(_s) document.head.appendChild(_s)
})(); })();
</script> </script>
</textarea </textarea>
>
<div class="other-wrap"> <div class="other-wrap">
<a class="btn btn-blue btn-large mr10" href="javascript:void(0);" @click="jiazai">点击体验</a> <a class="btn btn-blue btn-large mr10" href="javascript:void(0);" @click="jiazai">点击体验</a>
<a class="btn btn-blue btn-large" href="javascript:void(0);" @click="getCopy('NormalCodeTextarea1')"><span>复制代码</span></a> <a class="btn btn-blue btn-large" href="javascript:void(0);" @click="getCopy('NormalCodeTextarea1')"><span>复制代码</span></a>
@ -38,38 +39,37 @@
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { defineProps, defineEmits } from 'vue'; import { ref, onMounted, defineProps, defineEmits } from 'vue';
import { getInfo } from '@/api/login';
// uniqueToken
const props = defineProps<{ const props = defineProps<{
tokeninfo?: any; tokeninfo?: any;
siteUrl?: string; siteUrl?: string;
uniqueToken: string;
floatConfig?: { //
pcImage: string;
mobileImage: string;
};
}>();
const emit = defineEmits<{
(e: 'cgetCopy', id: string): void;
}>(); }>();
const emit = defineEmits<{ (e: 'cgetCopy', id: string): void }>(); //
const uniqueToken = ref('');
function jiazai() { function jiazai() {
// const token = props.tokeninfo?.token_md5 || ''; const token = props.uniqueToken || '';
const token = uniqueToken.value || '';
window.open(`${location.origin}/chat/index?token=${token}&noCanClose=1`); window.open(`${location.origin}/chat/index?token=${token}&noCanClose=1`);
} }
async function fetchUniqueToken() { //
const res = await getInfo();
console.log(res.data.tokenInfo);
if (res.data && res.data.tokenInfo) {
uniqueToken.value = res.data.tokenInfo.uniqueToken || '';
}
}
function getCopy(id: string) { function getCopy(id: string) {
emit('cgetCopy', id); emit('cgetCopy', id);
} }
onMounted(() => {
fetchUniqueToken();
});
</script> </script>
<style> <style>
.a { .a {
display: none; display: none;
@ -77,4 +77,4 @@ onMounted(() => {
border-radius: 8px; border-radius: 8px;
overflow: hidden; overflow: hidden;
} }
</style> </style>

64
im-admin-ui/src/views/im/code/index.vue

@ -2,12 +2,20 @@
<div class="getCode_container"> <div class="getCode_container">
<div class="content"> <div class="content">
<el-card shadow="never"> <el-card shadow="never">
<!-- 使用悬浮球设置组件 -->
<FloatBallSetting
ref="floatBallSettingRef"
:token="uniqueToken"
@save="handleFloatBallConfigSaved"
@update:config="handleFloatBallConfigUpdate"
/>
<el-collapse v-model="activeName" accordion> <el-collapse v-model="activeName" accordion>
<el-collapse-item title="超链接" name="1"> <el-collapse-item title="超链接" name="1">
<alink :tokeninfo="token" :site-url="siteUrl" @cget-copy="getCopy"></alink> <alink :tokeninfo="token" :site-url="siteUrl" :unique-token="uniqueToken" @cget-copy="getCopy"></alink>
</el-collapse-item> </el-collapse-item>
<el-collapse-item title="网页内嵌" name="2"> <el-collapse-item title="网页内嵌" name="2">
<wangye :tokeninfo="token" :site-url="siteUrl" @cget-copy="getCopy"></wangye> <wangye :tokeninfo="token" :site-url="siteUrl" :unique-token="uniqueToken" :float-config="floatBallConfig" @cget-copy="getCopy"></wangye>
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
</el-card> </el-card>
@ -21,11 +29,15 @@ import { ref, computed, onMounted, getCurrentInstance } from 'vue';
// import { adminAppCustomer, appReset } from '@/api/kefu'; // import { adminAppCustomer, appReset } from '@/api/kefu';
import alink from './components/alink.vue'; import alink from './components/alink.vue';
import wangye from './components/wangye.vue'; import wangye from './components/wangye.vue';
import FloatBallSetting from './components/FloatBallSetting.vue';
import type { FloatBallConfig } from './components/FloatBallSetting.vue';
import { getInfo } from '@/api/login';
// import kaifa from './components/kaifa'; // import kaifa from './components/kaifa';
// import setting from './components/setting'; // import setting from './components/setting';
const activeName = ref('1'); const activeName = ref('1');
const floatBallSettingRef = ref<InstanceType<typeof FloatBallSetting>>();
const uniqueToken = ref('');
const { proxy } = getCurrentInstance() as any; const { proxy } = getCurrentInstance() as any;
// const store = useStore(); // const store = useStore();
@ -33,7 +45,11 @@ const { proxy } = getCurrentInstance() as any;
// const categoryId = computed(() => store.state.userLevel?.categoryId); // const categoryId = computed(() => store.state.userLevel?.categoryId);
// const labelWidth = computed(() => (isMobile.value ? undefined : 75)); // const labelWidth = computed(() => (isMobile.value ? undefined : 75));
// const labelPosition = computed(() => (isMobile.value ? 'top' : 'left')); // const labelPosition = computed(() => (isMobile.value ? 'top' : 'left'));
// 👇
const floatBallConfig = ref<FloatBallConfig>({
pcImage: '',
mobileImage: '',
});
const token = ref<any>(''); const token = ref<any>('');
const canfrime = ref(false); const canfrime = ref(false);
const srcUrl = ref(`${location.origin}/customerServer.js`); const srcUrl = ref(`${location.origin}/customerServer.js`);
@ -42,7 +58,10 @@ const cloneTip = ref(false);
const canCustomerServer = ref(''); const canCustomerServer = ref('');
const linkUrl = computed(() => `${location.origin}/chat/index?token=${token.value?.token_md5}&noCanClose=1`); const linkUrl = computed(() => `${location.origin}/chat/index?token=${token.value?.token_md5}&noCanClose=1`);
onMounted(() => {
// uniqueToken
fetchAgentToken();
});
// onMounted(() => { // onMounted(() => {
// getAdminAppCustomer(); // getAdminAppCustomer();
// }); // });
@ -60,6 +79,36 @@ const linkUrl = computed(() => `${location.origin}/chat/index?token=${token.valu
// // ignore if module not present // // ignore if module not present
// } // }
// } // }
// uniqueToken
async function fetchAgentToken() {
try {
const res = await getInfo();
if (res.data?.tokenInfo?.uniqueToken) {
// token
uniqueToken.value = res.data.tokenInfo.uniqueToken;
console.log('✅ 获取成功 uniqueToken =', uniqueToken.value);
}
} catch (e) {
console.error('获取token失败', e);
}
}
//
function handleFloatBallConfigUpdate(config: FloatBallConfig) {
floatBallConfig.value = config;
//
console.log('悬浮球配置已更新:', config);
}
//
function handleFloatBallConfigSaved(config: FloatBallConfig) {
floatBallConfig.value = config;
//
console.log('悬浮球配置已保存:', config);
// API
// saveFloatBallConfigToServer(config);
}
function resetToken() { function resetToken() {
canfrime.value = true; canfrime.value = true;
@ -144,7 +193,7 @@ function copyToClipboard(elem: HTMLElement) {
} }
</script> </script>
<style> <style lang="scss">
.getCode_container { .getCode_container {
.content { .content {
width: 100%; width: 100%;
@ -242,6 +291,7 @@ function copyToClipboard(elem: HTMLElement) {
} }
} }
</style> </style>
<style scoped> <style scoped>
.ivu-modal-confirm { .ivu-modal-confirm {
display: flex; display: flex;
@ -252,4 +302,4 @@ function copyToClipboard(elem: HTMLElement) {
height: 40px !important; height: 40px !important;
margin-right: 30px; margin-right: 30px;
} }
</style> </style>

25
im-admin/ruoyi-im/src/main/java/org/dromara/im/controller/ImAgentController.java

@ -7,6 +7,8 @@ import lombok.RequiredArgsConstructor;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.*; import jakarta.validation.constraints.*;
import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaCheckPermission;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.im.domain.ImAgent;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.dromara.common.idempotent.annotation.RepeatSubmit; import org.dromara.common.idempotent.annotation.RepeatSubmit;
@ -91,6 +93,29 @@ public class ImAgentController extends BaseController {
return toAjax(imAgentService.updateByBo(bo)); return toAjax(imAgentService.updateByBo(bo));
} }
/**
* 更新代理悬浮球图片配置
*/
@Log(title = "代理关联", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PostMapping("/updateFloatBall")
public R<Void> updateFloatBall(@RequestBody ImAgentBo bo) {
imAgentService.updateFloatBall(bo);
return R.ok();
}
/**
* 根据token获取代理悬浮球配置
*/
@GetMapping("/infoByToken")
public R<ImAgentVo> infoByToken(@RequestParam String token) {
ImAgent agent = imAgentService.getAgentByToken(token);
if (agent == null) {
return R.fail("代理不存在");
}
return R.ok(MapstructUtils.convert(agent, ImAgentVo.class));
}
/** /**
* 删除代理关联 * 删除代理关联
* *

9
im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/ImAgent.java

@ -66,5 +66,14 @@ public class ImAgent implements TransPojo {
*/ */
private Long maxCustomer; private Long maxCustomer;
/**
* PC端悬浮球图片
*/
private String pcFloatBall;
/**
* 移动端悬浮球图片
*/
private String mobileFloatBall;
} }

8
im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/bo/ImAgentBo.java

@ -66,5 +66,13 @@ public class ImAgentBo {
*/ */
private Date packageExpireTime; private Date packageExpireTime;
/**
* PC端悬浮球图片
*/
private String pcFloatBall;
/**
* 移动端悬浮球图片
*/
private String mobileFloatBall;
} }

9
im-admin/ruoyi-im/src/main/java/org/dromara/im/domain/vo/ImAgentVo.java

@ -77,5 +77,14 @@ public class ImAgentVo implements Serializable {
*/ */
private Date packageExpireTime; private Date packageExpireTime;
/**
* PC端悬浮球图片
*/
private String pcFloatBall;
/**
* 移动端悬浮球图片
*/
private String mobileFloatBall;
} }

5
im-admin/ruoyi-im/src/main/java/org/dromara/im/service/IImAgentService.java

@ -95,4 +95,9 @@ public interface IImAgentService {
* @return 如果套餐即将到期七天内返回到对应提示 每天只提示一次 * @return 如果套餐即将到期七天内返回到对应提示 每天只提示一次
*/ */
String checkIsExpiredTask(Long sysId); String checkIsExpiredTask(Long sysId);
/**
* 更新悬浮球图片配置
*/
void updateFloatBall(ImAgentBo bo);
} }

14
im-admin/ruoyi-im/src/main/java/org/dromara/im/service/impl/ImAgentServiceImpl.java

@ -246,4 +246,18 @@ public class ImAgentServiceImpl implements IImAgentService {
return ""; return "";
} }
@Override
public void updateFloatBall(ImAgentBo bo) {
// 根据token查询当前代理
ImAgent agent = getAgentByToken(bo.getUniqueToken());
if (agent == null) {
throw new RuntimeException("代理不存在"+bo.getUniqueToken());
}
// 设置悬浮球图片
agent.setPcFloatBall(bo.getPcFloatBall());
agent.setMobileFloatBall(bo.getMobileFloatBall());
baseMapper.updateById(agent);
}
} }

Loading…
Cancel
Save