Files
zyt/artifacts/wecom-member-sync/ui-preview.mjs
T
2026-09-09 14:04:09 +08:00

78 lines
5.2 KiB
JavaScript

import { createServer } from '../../admin/node_modules/vite/dist/node/index.js'
import vue from '../../admin/node_modules/@vitejs/plugin-vue/dist/index.mjs'
import fs from 'node:fs'
const root = 'D:/web/zyt/admin'
const apiNames = [...fs.readFileSync(`${root}/src/api/first_visit.ts`, 'utf8').matchAll(/export (?:async )?function (wecomPromotion\w+)\s*\(/g)].map(match => match[1])
const members = [
{ id: 1, admin_id: 1, name: '测试许可', userid: 'test_xuke', enabled: 1, reception_available: true },
{ id: 2, admin_id: 2, name: '测试旧医助', userid: 'test_old', enabled: 0, reception_available: false }
].map(member => ({ ...member, dept_ids: [1], dept_names: ['测试部门'], display_dept_id: 1,
status: member.enabled, today_count: 0, total_count: 0, daily_limit: 0, is_in_remote_range: true, sync_status: 1 }))
const overview = {
automation_installed: false, meta: { scope_label: '隔离验证', generated_at: '' },
config: { configured: true, ready: true, missing: [], callback_ready: true },
summary: { configured_apps: 1, pool_count: 1, online_links: 1, today_clicks: 0 },
member_options: members, operator_options: [], department_options: [{ id: 1, name: '测试部门' }], links: [],
pools: [{ id: 99, name: '仅许可接待测试方案', public_key: 'test-only', status: 1, member_admin_ids: [1, 2],
main_url: 'https://work.weixin.qq.com/ca/test-only', can_operate: true, can_manage_access: true, can_delete: true,
operator_admin_ids: [], member_rules: members, automation_config: { backup_member_admin_ids: [] },
official_link: { id: 199, remote_link_id: 'test-link', range_userids: ['test_xuke', 'test_old'], range_department_ids: [], last_sync_time: 1788920000 },
dispatch_sync: { status: 1, desired_version: 2, applied_version: 1, last_error: '' }
}]
}
for (const id of [100, 101]) {
const pool = structuredClone(overview.pools[0])
Object.assign(pool, { id, name: `批量验证方案 ${id}`, public_key: `test-only-${id}` })
overview.pools.push(pool)
}
overview.summary.pool_count = overview.summary.online_links = overview.pools.length
const fixture = `const overview = ${JSON.stringify(overview)};
async function invoke(name, params) {
if (name === 'wecomPromotionOverview') return structuredClone(overview);
if (name === 'wecomPromotionSyncMemberRange') {
const pool = overview.pools.find(item => item.id === params.pool_id);
const mode = new URLSearchParams(location.search).get('mode');
if (mode === 'failure' || (mode === 'mixed' && pool.id === 100)) {
pool.dispatch_sync.status = 3; pool.dispatch_sync.last_error = '模拟企微网络错误';
pool.member_rules.forEach(row => {row.sync_status = 3; row.sync_error = '模拟企微网络错误';});
return {pool_id:pool.id,sync_status:'failed',sync_error:'模拟企微网络错误',sync_queued:true};
}
pool.official_link.range_userids = ['test_xuke']; pool.official_link.last_sync_time = Math.floor(Date.now()/1000);
pool.dispatch_sync = {status:0,desired_version:2,applied_version:2,last_error:''};
pool.member_rules.forEach(row => {row.is_in_remote_range = row.enabled === 1; row.sync_status = 0;});
return {pool_id:pool.id,sync_status:'synced',sync_error:'',sync_queued:false,range_userids:['test_xuke'],range_department_ids:[]};
}
throw new Error('隔离页面未实现该操作:' + name);
}
${apiNames.map(name => `export function ${name}(params) {return invoke('${name}',params);}`).join('\n')}`
const server = await createServer({
configFile: false, root, base: '/',
cacheDir: 'D:/web/zyt/artifacts/wecom-member-sync/vite-cache',
optimizeDeps: { entries: [], include: ['vue', 'element-plus', '@element-plus/icons-vue'] },
resolve: { alias: { '@': `${root}/src` } },
plugins: [{
name: 'member-sync-isolated-fixture', enforce: 'pre',
resolveId(id) {
if (id === '@/api/first_visit' || id.endsWith('/src/api/first_visit')) return '\0member-sync-api'
if (id === '/__member-sync-entry.js') return '\0member-sync-entry'
},
load(id) {
if (id === '\0member-sync-api') return fixture
if (id === '\0member-sync-entry') return `import {createApp} from 'vue';import ElementPlus from 'element-plus';import 'element-plus/dist/index.css';import View from '/src/views/first_visit/wecom_promotion/index.vue';createApp(View).use(ElementPlus).mount('#app');`
},
configureServer(dev) {
dev.middlewares.use((req, res, next) => {
if (!req.url?.startsWith('/__member-sync-check')) return next()
res.setHeader('Content-Type', 'text/html;charset=utf-8')
res.end('<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><title>企微成员同步隔离验证</title></head><body><p>隔离验证:虚构数据,不连接企业微信</p><div id="app"></div><script type="module" src="/__member-sync-entry.js"></script></body></html>')
})
}
}, vue()],
server: { host: '127.0.0.1', port: 5587, strictPort: true, open: false }
})
await server.listen()
console.log('Isolated UI: http://127.0.0.1:5587/__member-sync-check')
for (const event of ['SIGINT', 'SIGTERM']) process.on(event, async () => { await server.close(); process.exit(0) })