npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xm-dev/sql-viewer-vue3

v1.1.2

Published

Vue3 SQL editor component based on CodeMirror 6 & Element Plus, with syntax highlight, autocomplete, SQL formatter and database query console for admin projects.

Readme

安装

npm install @xm-dev/sql-viewer-vue3

# 你的项目需有 vue3 和 element plus
npm install vue element-plus @element-plus/icons-vue

全局注册

main.js

import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);

// 引入组件并注册
import SqlViewer from '@xm-dev/sql-viewer-vue3';
app.use(SqlViewer);

app.mount('#app');

vue

<template>
	<SqlViewer />
</template>

按需引入

vue

<template>
	<SqlViewer />
</template>

<script setup>
	import { SqlViewer } from '@xm-dev/sql-viewer-vue3';
</script>

页面效果

  • 页面效果跟简化版的 Navicat 差不多
  • 执行结果, 默认是用 el-table-v2, 可以用 <template #table> 换成其他虚拟表格, 比如 VxeTable

1784099150332

示例代码

<template>
	<SqlViewer
		v-loading="load"
		:panel="{
			main: { layout: 'horizontal', lazy: false },
			left: { min: '200', size: '300' },
			right: { min: '30%' },
			sub: { layout: 'vertical', lazy: false },
			top: { min: '30%' },
			bottom: { min: '30%' },
		}"
		v-model:tab="tab"
		:tabs="tabs"
		:tree="tree"
		:treeProps="treeProps"
		v-model:sql="sql"
		@run="getRun"
		:tips="tips"
		:info="info"
		:infoType="infoType"
		:result="result"
		:cols="cols"
	>
		<!-- 我更喜欢用VxeTable的虚拟表格, 高级版VxeTable效果更像Navicat -->
		<template #table>
			<div class="VxeTable">
				<vxe-table ref="VxeTableRef" v-bind="vxe_h()" :data="result" align="left">
					<vxe-column type="seq" width="50" fixed="left" />
					<vxe-column :field="v.field" :title="v.title" min-width="120" v-for="v in cols" />
				</vxe-table>
			</div>
		</template>
	</SqlViewer>
</template>

<script setup>
	defineOptions({ name: 'SQLEditor' });
	const role = 'SQLEditor';
	const Lang = useLang('SQLEditor');
	const Lang2 = useLang('common');

	// 编辑器 ------------------------------------------------------------------------------------------
	import { SqlViewer } from '@xm-dev/sql-viewer-vue3';
	const load = ref(false);

	// 获取数据
	import { GetInfo } from '@/api/dev/sql';
	const tree = ref({});
	const treeProps = ref({
		table: { value: 'name', label: 'name', children: 'column' },
		view: { value: 'name', label: 'name', children: 'column' },
		SP: { value: 'name', label: 'name', children: 'column' },
	});
	const getTabsInfo = async (type, key) => {
		load.value = true;
		const res = await GetInfo({ object_type: type });
		load.value = false;

		if (res.code === 0) tree.value[key] = res?.data || [];
		else XmNotify(res.msg, 'error');
	};

	// LeftArea ------------------------------------------------------------------------------------------
	const tab = ref('table');
	const tabs = computed(() => [
		{ label: '表', name: 'table' },
		{ label: '视图', name: 'view' },
		{ label: '存储过程', name: 'SP' },
	]);

	// TopArea ------------------------------------------------------------------------------------------
	const sql = ref('');
	import { ExecuteSql } from '@/api/dev/sql';
	const getRun = async sql => {
		if (!sql.trim()) return XmNotify('请输入SQL语句', 'warning');
		clear();

		load.value = true;
		const res = await ExecuteSql({ sql });
		load.value = false;

		if (res.code === 0) {
			info.value = `${res?.data?.length || 0} 条记录`;
			infoType.value = 'success';
			result.value = res?.data || [];
		} else {
			XmNotify(res.msg, 'error');
			info.value = res.msg;
			infoType.value = 'error';
			result.value = [];
		}

		if (result.value.length > 0) {
			const obj = { ...result.value[0] };

			for (const v in obj) {
				if (['_X_ROW_KEY'].includes(v)) continue;
				cols.value.push({ field: v, title: v, key: v, dataKey: v, width: 120, align: 'left' });
			}
		}
	};

	// BottomArea ------------------------------------------------------------------------------------------
	const info = ref('');
	const infoType = ref('');
	const result = ref([]);
	const cols = ref([]);
	const clear = () => {
		info.value = '';
		infoType.value = '';
		result.value = [];
		cols.value = [];
	};
	// Vxe 预设配置
	const vxe_h = () => {
		const h_def = XmVxe.h_def();
		const h_copy = XmVxe.h_copy();
		const vxe_h = { ...h_def, ...h_copy };
		return vxe_h;
	};

	// Tips ------------------------------------------------------------------------------------------
	const tips = ref([]);
	const getNames = data => {
		const names = new Set();
		Object.values(data).forEach(collection => {
			if (Array.isArray(collection))
				collection.forEach(item => {
					if (item && typeof item === 'object' && 'name' in item) names.add(item.name);
				});
		});
		return Array.from(names);
	};

	// 周期 ------------------------------------------------------------------------------------------
	const init = async () => {
		await getTabsInfo('表', 'table');
		await getTabsInfo('视图', 'view');
		await getTabsInfo('存储过程', 'SP');
		tips.value = getNames(tree.value);
	};
	onMounted(() => init());
</script>

<style lang="scss" scoped>
	.VxeTable {
		height: 100%;
	}
</style>

Props 和 Emits

const props = defineProps({ // 面板配置 ------------------------------------- panel: { type: Object, default: () => ({}) }, // LeftArea ------------------------------------- tab: { type: String, default: '' }, // 选中的标签页 table | view | function tabs: { type: Array, default: () => null }, tree: { type: Object,
default: () => ({}) }, // 标签页上的树状数据 treeProps: { type: Object, default: () => ({}) }, // TopArea ------------------------------------- sql: { type: String, default: '' }, // 编辑器上的语句 tips: { type: Array, default: () => [] }, // 编辑器补全提示 // BottomArea ------------------------------------- info: {
type: String, default: '' }, // 信息 infoType: { type: String, default: '' }, // 信息类型 success | warning | infoType | info result: { type: Array, default: () => [] }, // 执行结果 cols: { type: Array, default: () => [] }, // 执行结果中筛选出字段列 渲染表格 }); const emits = defineEmits(['update:tab', 'tabChange',
'update:sql', 'run']);
面板配置
// 默认面板配置 { main: { layout: 'horizontal', lazy: false }, left: { min: '200', size: '300' }, right: { min: '30%' }, sub: { layout: 'vertical', lazy: false }, top: { min: '30%' }, bottom: { min: '30%' }, } https://element-plus.org/zh-CN/component/splitter 按需调整版块布局
标签页配置
// 默认标签页配置 [ { label: '表', name: 'table' }, { label: '视图', name: 'view' }, { label: '函数', name: 'function' }, ] 正常就这三种就够了, 不用调

自定义

想自定义或者查看传参和事件, 直接翻源码吧.

环境

# 开发此包的环境
node -v		# v25.0.0
npm -v		# 11.6.2

# 示例代码的环境
node -v		# v22.0.0
npm -v		# 10.5.1
pnpm -v		# 10.34.4

⚠️ 重要使用声明

引用的相关插件,请自行查看对应的协议。 所有违规、违法、侵权使用产生的全部法律责任,均由使用者自行承担,项目作者不承担任何连带责任与法律责任

📜 开源协议

Apache 2.0

Copyright (c) 2026 xiaomu-dev

本项目基于 Apache License 2.0 协议开源

许可范围

允许

  • 个人/企业免费学习、研究、自用、商用交付
  • 自由修改源码、新增业务逻辑
  • 闭源二次开发、私有化部署、打包商用售卖
  • 分发、修改、衍生开发,衍生代码可自行选择私有/开源协议

强制遵守条款

  1. 分发时完整保留本项目 LICENSE 协议文件;
  2. 所有修改过的源文件内标注改动记录;
  3. 保留原版权署名、NOTICE 文件内容,不得抹除原作者信息;
  4. 本协议授予配套专利永久免费授权;若使用者以本项目代码起诉原作者专利侵权,其全部使用权自动终止。

免责说明

本软件按「现状」分发,无任何明示或隐含担保;使用者使用、改造本项目产生的一切商业损失、安全风险、法律纠纷均由使用者自行承担,原作者不承担任何连带责任。