mirror of
https://github.com/hansjone/dsh-im-ops.git
synced 2026-10-09 03:03:24 +08:00
120 lines
6.6 KiB
JavaScript
120 lines
6.6 KiB
JavaScript
import * as React from 'react';
|
|
|
|
import { DINGTALK_RPC_CHANNEL } from '@xmanrui/dsh-dingtalk/client-api';
|
|
import { DingtalkSettingsTab } from '@xmanrui/dsh-dingtalk/client-source';
|
|
import { FeishuSettingsTab } from './channels/feishu/index.js';
|
|
import { FEISHU_RPC_CHANNEL } from './channels/feishu/api.js';
|
|
import { installFeishuStyles } from './channels/feishu/styles.js';
|
|
import { WeixinSettingsTab } from './channels/weixin/index.js';
|
|
import { WEIXIN_RPC_CHANNEL } from './channels/weixin/api.js';
|
|
import { installWeixinStyles } from './channels/weixin/styles.js';
|
|
import { installImStyles } from './styles.js';
|
|
|
|
const h = React.createElement;
|
|
|
|
export const name = 'im-settings';
|
|
export const inject = ['slots', 'connection'];
|
|
|
|
const CHANNELS = Object.freeze([
|
|
{ id: 'weixin', label: '微信' },
|
|
{ id: 'feishu', label: '飞书' },
|
|
{ id: 'dingtalk', label: '钉钉' },
|
|
]);
|
|
|
|
function WeixinLogo() {
|
|
return h('span', { className: 'dim-logo dim-logoWeixin', 'aria-hidden': 'true' },
|
|
h('svg', { viewBox: '0 0 24 24', focusable: 'false' },
|
|
h('path', {
|
|
fill: 'currentColor',
|
|
d: 'M8.691 2.188C3.891 2.188 0 5.476 0 9.53c0 2.212 1.17 4.203 3.002 5.55a.59.59 0 0 1 .213.665l-.39 1.48c-.019.07-.048.141-.048.213 0 .163.13.295.29.295a.326.326 0 0 0 .167-.054l1.903-1.114a.864.864 0 0 1 .717-.098 10.16 10.16 0 0 0 2.837.403c.276 0 .543-.027.811-.05-.857-2.578.157-4.972 1.932-6.446 1.703-1.415 3.882-1.98 5.853-1.838-.576-3.583-4.196-6.348-8.596-6.348zM5.785 5.991c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178A1.17 1.17 0 0 1 4.623 7.17c0-.651.52-1.18 1.162-1.18zm5.813 0c.642 0 1.162.529 1.162 1.18a1.17 1.17 0 0 1-1.162 1.178 1.17 1.17 0 0 1-1.162-1.178c0-.651.52-1.18 1.162-1.18zm5.34 2.867c-1.797-.052-3.746.512-5.28 1.786-1.72 1.428-2.687 3.72-1.78 6.22.942 2.453 3.666 4.229 6.884 4.229.826 0 1.622-.12 2.361-.336a.722.722 0 0 1 .598.082l1.584.926a.272.272 0 0 0 .14.047c.134 0 .24-.111.24-.247 0-.06-.023-.12-.038-.177l-.327-1.233a.582.582 0 0 1-.023-.156.49.49 0 0 1 .201-.398C23.024 18.48 24 16.82 24 14.98c0-3.21-2.931-5.837-6.656-6.088V8.89c-.135-.01-.27-.027-.407-.03zm-2.53 3.274c.535 0 .969.44.969.982a.976.976 0 0 1-.969.983.976.976 0 0 1-.969-.983c0-.542.434-.982.97-.982zm4.844 0c.535 0 .969.44.969.982a.976.976 0 0 1-.969.983.976.976 0 0 1-.969-.983c0-.542.434-.982.969-.982z',
|
|
}),
|
|
));
|
|
}
|
|
|
|
function FeishuLogo() {
|
|
return h('span', { className: 'dim-logo dim-logoFeishu', 'aria-hidden': 'true' },
|
|
h('svg', { viewBox: '0 0 24 24', focusable: 'false' },
|
|
h('path', { fill: '#00D6B9', d: 'M7.2 4.5h7.6c1.2 0 2.1.55 2.7 1.58 1.05 1.8 1.55 3.45 1.58 4.95-2.04-.62-4.2-.15-6.22 1.45C11.3 9.7 9.42 7.04 7.2 4.5Z' }),
|
|
h('path', { fill: '#1456B8', d: 'M10.8 13.55c3.3-2.93 5.72-4.24 9.47-2.52-1.2 1.45-2.27 4.18-3.86 5.43-1.67 1.31-3.9.5-5.61-.64v-2.27Z' }),
|
|
h('path', { fill: '#3370FF', d: 'M4.4 8.35c3.47 3.61 7.25 6.1 10.33 5.7 1.06-.14 2.2-.72 3.4-1.72-1.04 2.65-2.6 4.8-5.06 6-2.46 1.2-5.56.52-7.42-.72A2.76 2.76 0 0 1 4.4 15.3V8.35Z' }),
|
|
));
|
|
}
|
|
|
|
function DingtalkLogo() {
|
|
return h('span', { className: 'dim-logo dim-logoDingtalk', 'aria-hidden': 'true' },
|
|
h('svg', { viewBox: '0 0 48 48', focusable: 'false' },
|
|
h('path', {
|
|
fill: 'currentColor',
|
|
d: 'M37.05 22.783c-6.758-5.216-14.378-12.128-22.73-19.538-.655-.585-1.242-.354-1.536.42-1.88 4.973-.058 9.386 2.889 11.932s7.368 4.912 10.058 6.155c.105.049.013.203-.093.163-4.953-2.182-8.397-3.765-13.07-7.368-.497-.388-1.01-.242-1.07.521-.384 4.748 2.657 8.483 6.058 9.745 2.1.781 4.398 1.212 6.53 1.474.109.015.084.178-.027.178-2.747.01-6.058-.654-8.935-1.751-.606-.233-.818.25-.722.633.491 2.008 2.974 5.076 6.926 5.73a12 12 0 0 0 2.228.115c.164 0 .208.089.154.217q-2.685 4.6-2.803 4.797c-.091.152-.036.275.156.275h3.543c.164 0 .264.106.18.246l-4.958 8.196c-.191.328.035.565.395.301s15.212-11.133 15.636-11.448c.195-.142.148-.327-.124-.327h-3.18c-.206 0-.252-.14-.111-.28.14-.141 3.602-3.594 4.837-4.888 1.283-1.35 1.938-3.825-.231-5.498',
|
|
}),
|
|
));
|
|
}
|
|
|
|
function ChannelLogo({ channel }) {
|
|
if (channel === 'weixin') return h(WeixinLogo);
|
|
if (channel === 'feishu') return h(FeishuLogo);
|
|
return h(DingtalkLogo);
|
|
}
|
|
|
|
export function IMSettingsTab({ dingtalkRpcCall, feishuRpcCall, weixinRpcCall }) {
|
|
const [selected, setSelected] = React.useState('weixin');
|
|
const active = CHANNELS.find((channel) => channel.id === selected) ?? CHANNELS[0];
|
|
return h('section', { className: 'dim-page', 'aria-label': 'IM机器人设置' },
|
|
h('header', { className: 'dim-title' },
|
|
h('p', null, '通过扫码把机器人接入 DeepSeek Harness'),
|
|
h('div', { className: 'dim-channelCount' }, `${CHANNELS.length} 个渠道`),
|
|
),
|
|
h('div', { className: 'dim-layout' },
|
|
h('nav', { className: 'dim-rail', role: 'tablist', 'aria-label': 'IM 渠道' },
|
|
CHANNELS.map((channel) => h('button', {
|
|
key: channel.id,
|
|
type: 'button',
|
|
role: 'tab',
|
|
id: `dim-tab-${channel.id}`,
|
|
className: 'dim-channel',
|
|
'aria-selected': channel.id === active.id,
|
|
'aria-controls': `dim-panel-${channel.id}`,
|
|
onClick: () => setSelected(channel.id),
|
|
},
|
|
h(ChannelLogo, { channel: channel.id }),
|
|
h('span', { className: 'dim-channelCopy' },
|
|
h('strong', null, channel.label),
|
|
)))),
|
|
h('div', { className: 'dim-divider', 'aria-hidden': 'true' }),
|
|
h('main', {
|
|
className: 'dim-panel',
|
|
role: 'tabpanel',
|
|
id: `dim-panel-${active.id}`,
|
|
'aria-labelledby': `dim-tab-${active.id}`,
|
|
}, active.id === 'weixin'
|
|
? h(WeixinSettingsTab, { rpcCall: weixinRpcCall })
|
|
: active.id === 'feishu'
|
|
? h(FeishuSettingsTab, { rpcCall: feishuRpcCall })
|
|
: h(DingtalkSettingsTab, { rpcCall: dingtalkRpcCall })),
|
|
),
|
|
);
|
|
}
|
|
|
|
export function apply(ctx) {
|
|
ctx.effect(() => {
|
|
const disposers = [installFeishuStyles(), installWeixinStyles(), installImStyles()];
|
|
return () => {
|
|
for (const dispose of disposers.reverse()) dispose();
|
|
};
|
|
}, 'im-settings: install combined channel styles');
|
|
|
|
const feishuRpcCall = (endpoint, payload, signal) =>
|
|
ctx.connection.rpc.call(FEISHU_RPC_CHANNEL, endpoint, payload, signal);
|
|
const weixinRpcCall = (endpoint, payload, signal) =>
|
|
ctx.connection.rpc.call(WEIXIN_RPC_CHANNEL, endpoint, payload, signal);
|
|
const dingtalkRpcCall = (endpoint, payload, signal) =>
|
|
ctx.connection.rpc.call(DINGTALK_RPC_CHANNEL, endpoint, payload, signal);
|
|
|
|
ctx.slots.inject('settings.plugins.tab', () => ctx.slots.register({
|
|
name: 'settings.plugins.tab',
|
|
id: 'im',
|
|
order: 20,
|
|
label: 'IM机器人',
|
|
inject: () => ({ dingtalkRpcCall, feishuRpcCall, weixinRpcCall }),
|
|
}, IMSettingsTab));
|
|
}
|