@nj_wangrizhen/webc-lib 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # @nj_wangrizhen/webc-lib
2
+
3
+ ## 简介
4
+ `@nj_wangrizhen/webc-lib` 轻量 Vue 组件工具库,使用逻辑对标 ElementUI:
5
+ 1. 组件全局自动注册,页面直接写标签使用,无需单独 import;
6
+ 2. 工具方法自动挂载至 `window.$webc`,任意页面直接调用;
7
+ 3. 兼容 Vue2 / Vue3 / uni-app H5;
8
+ 4. 内置组件:`webc-input` 输入框、`webc-service-btn` 企微客服按钮;
9
+ 5. 内置工具:环境判断、接口请求、一键打开企业微信客服。
10
+
11
+ ## 安装
12
+ ```bash
13
+ # pnpm(推荐)
14
+ pnpm add @nj_wangrizhen/webc-lib
15
+
16
+ # npm
17
+ npm install @nj_wangrizhen/webc-lib
18
+
19
+ # yarn
20
+ yarn add @nj_wangrizhen/webc-lib
21
+
22
+ # Vue2 使用教程
23
+ import Vue from 'vue'
24
+ import App from './App.vue'
25
+ import WebcLib from '@wangrizhen/webc-lib'
26
+
27
+ // 全局注册全部组件
28
+ Vue.use(WebcLib)
29
+
30
+ new Vue({
31
+ render: h => h(App)
32
+ }).$mount('#app')
33
+
34
+ # Vue3 使用教程
35
+ import { createApp } from 'vue'
36
+ import App from './App.vue'
37
+ import WebcLib from '@wangrizhen/webc-lib'
38
+
39
+ const app = createApp(App)
40
+ app.use(WebcLib)
41
+
42
+ app.mount('#app')
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .movable-view[data-v-1d2e65a3]{-webkit-tap-highlight-color:transparent!important;outline:none!important}.movable-view[data-v-1d2e65a3]:active{box-shadow:0 4px 12px #1968fc!important}
@@ -0,0 +1,262 @@
1
+ import { openBlock as l, createElementBlock as c, normalizeStyle as a, createElementVNode as u, normalizeClass as g, createCommentVNode as m } from "vue";
2
+ const w = {
3
+ // 环境判断方法
4
+ isDev() {
5
+ const e = window.location.hostname;
6
+ return e === "localhost" || e === "127.0.0.1" || e.includes("192.168.");
7
+ },
8
+ /**
9
+ * 获取公共企业设置
10
+ */
11
+ getDynamic: (e) => new Promise((t, i) => {
12
+ fetch(`${e}`).then((n) => n.json()).then((n) => {
13
+ if (!n || n.ret_code !== "10000" && n.code !== 200) {
14
+ i(n);
15
+ return;
16
+ } else
17
+ localStorage.setItem("tenantConfigData", JSON.stringify(n.data || {})), t(n);
18
+ }).catch((n) => {
19
+ i(n);
20
+ });
21
+ }),
22
+ /**
23
+ * 判断 当前 URL 是否 是 tmc 用户
24
+ * @returns {boolean} 是否为 tmc 用户
25
+ */
26
+ isTMCUser(e) {
27
+ return e.includes(window.location.host);
28
+ },
29
+ getwechaturl() {
30
+ const e = JSON.parse(localStorage.getItem("tenantConfigData")).wechaturl, t = document.createElement("a");
31
+ t.href = e, t.target = "_blank", document.body.appendChild(t), t.click(), document.body.removeChild(t);
32
+ }
33
+ };
34
+ window.$webc = w;
35
+ const f = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAD/klEQVR4nK2WUVLbSBCG//YuTyGFq0iq9g3lBDgnwJwg9gksnwDnBBEnwJwA+QSYEyCfAHMClLdULak1Fd7CMvlGso0wspGdfFUj9bTG0//0tEY2rYHr7n6Ss6acGpKjqU4DG9NPZbVE+uvC4m+pKlJJgOu+7+jxMZIUqAqmWNo6riLEaEtx4T+B3MO58tXmmI24JsrbFAukRz+mRXb2uOeYRRbfHmMtxWiluPB9Q+7xErNO8yMHrIoJv6VagQt3WwyO5Nw+XUzFFn/vYpVitBc8C276KtVaFv87ps8zsmL/HxAgUBFTYme3I6wMF76LGPMF0z9bKsJoz3BhUJf7cYNJcLuWtpsWp5NsZc6OGNHUcib8Jpb+PvWZYiEhCzmTx+yY7Yi0wEsBnd1zbi2e3ElvA3ncPb6VgReZ8EZ8JmsxmeiRiRN8RLNDRCQq8EwAihsovsL0T9qkPqV/Sa9OW59p6hGRIOIAR2KD20OezDHaHNIcU8UdlI5IYyj304vZLPgMRLCQUxbi56Jf+0hmxlgZRptD+h03721X2O/q+PlkvSwLplOy0sObMRfA6lus/hzPHYp7KD7D/aegJuwYASfYqWq1SO7NhS/uTAB7f0TASFm6bYynjh1oE0gxh1LCYnboPWEa4OtgTSGObR8aBdJE2SWe38f0lfQGzBkx5xc8q7Fa1wuoNrgK7DUChlhiS1NWvIe5HONs+CMCpnVDdceaUmnejQWQai5jLN+SxcPFkx3Z7ucN5nIqCzC75hqLgGXBlsHcY+bexyynkgCzC4K2sNaGOoipgw5mOdUEbH3wHxZtwOtz22cEFM7/Emzw3bhtxDMBpjuysYOV4/vaamSTM7DHNVKGRdg9Bu/Jw8FCdY+x1oZ5oycBta7kUkl97kEWnMyaSiArIVk5w+SHpCm+5UfrQw30WciReGs4HwIB35sb+iP6oaBUgAf1CeoPGJIsfkLLyP7I6D4sinWdd1dcGyziEH/CnE3mvPTZIKuxwGil5BP+SFnBDqPaKB7ixs/7rYe+pCv8CV/NBmd/g3Et+kw8GzcLplN8PVxeEH33gX6gKUsFeNiKBpMPmdzJ3n70Xy/cRf8eXT8LBbVwEvrVm7smWChAUA9BJ4xt4xviylgpwJNn4n7Ij//jjWjjmpMLcXWfXhXI9j47IfNAjAuzmjIN8IUq8KqAGaygyb+k1FeuXsFv02wcwf2nvk+kF8E9lQUs4oPIHvbktq9nW1MkE+x0oqwIn+pgkY0E5JO7c8w6bUJVH0pvUtn9PkFbPGvhD8TrJ1m4uEVFjLY2CBgS5BPmS7KCtERSf1XgGRsKoMj8ATPDbIS3jzGpErSI0dam8GYc5MG3W2V1UIVfwJ75zAMZtcIAAAAASUVORK5CYII=", b = (e, t) => {
36
+ const i = e.__vccOpts || e;
37
+ for (const [s, n] of t)
38
+ i[s] = n;
39
+ return i;
40
+ }, v = {
41
+ name: "WebcServiceBtn",
42
+ props: {
43
+ // 按钮文字
44
+ buttonText: {
45
+ type: String,
46
+ default: "拖动"
47
+ },
48
+ // 是否禁用拖动
49
+ disabled: {
50
+ type: Boolean,
51
+ default: !1
52
+ },
53
+ // 是否自动停靠
54
+ canDocking: {
55
+ type: Boolean,
56
+ default: !0
57
+ },
58
+ // 按钮默认位置离底部距离(px)
59
+ bottomPx: {
60
+ type: Number,
61
+ default: 200
62
+ },
63
+ // 按钮默认位置离右边距离(px)
64
+ rightPx: {
65
+ type: Number,
66
+ default: 20
67
+ },
68
+ // 自定义样式
69
+ customStyle: {
70
+ type: Object,
71
+ default: () => ({})
72
+ }
73
+ },
74
+ data() {
75
+ return {
76
+ isshow: !0,
77
+ x: 0,
78
+ y: 0,
79
+ oldX: 0,
80
+ oldY: 0,
81
+ isRemove: !0,
82
+ windowWidth: 0,
83
+ windowHeight: 0,
84
+ btnWidth: 40,
85
+ btnHeight: 40,
86
+ isDragging: !1,
87
+ startX: 0,
88
+ startY: 0
89
+ };
90
+ },
91
+ computed: {
92
+ // 区域样式
93
+ areaStyle() {
94
+ return {
95
+ width: "100%",
96
+ height: "100%",
97
+ position: "fixed",
98
+ top: "0",
99
+ left: "0",
100
+ right: "0",
101
+ bottom: "0",
102
+ zIndex: "9999",
103
+ pointerEvents: "none"
104
+ };
105
+ },
106
+ // 按钮样式(完全内联)
107
+ viewStyle() {
108
+ return { ...{
109
+ width: this.btnWidth + "px",
110
+ height: this.btnHeight + "px",
111
+ backgroundImage: `url(${f})`,
112
+ backgroundSize: "cover",
113
+ backgroundPosition: "center",
114
+ backgroundRepeat: "no-repeat",
115
+ borderRadius: "50px",
116
+ color: "#FFFFFF",
117
+ fontSize: "18px",
118
+ touchAction: "none",
119
+ display: "flex",
120
+ alignItems: "center",
121
+ justifyContent: "center",
122
+ position: "absolute",
123
+ cursor: "pointer",
124
+ pointerEvents: this.disabled ? "none" : "auto",
125
+ willChange: "transform",
126
+ transform: `translate(${this.x}px, ${this.y}px)`,
127
+ transition: this.isRemove ? "none" : "transform 0.25s ease",
128
+ userSelect: "none",
129
+ WebkitUserSelect: "none",
130
+ // 👇 添加这两行,移除点击高亮
131
+ WebkitTapHighlightColor: "transparent",
132
+ outline: "none"
133
+ }, ...this.customStyle };
134
+ }
135
+ },
136
+ created() {
137
+ const e = localStorage.getItem("tenantConfigData"), t = e ? JSON.parse(e) : null;
138
+ if (!(t != null && t.wechaturl)) {
139
+ this.isshow = !1;
140
+ return;
141
+ }
142
+ if (!this.isWechatEnv()) {
143
+ this.isshow = !1;
144
+ return;
145
+ }
146
+ },
147
+ mounted() {
148
+ this.isshow != !1 && (this.getSysInfo(), window.addEventListener("resize", this.handleResize), document.addEventListener("touchmove", this.handleTouchMove, { passive: !1 }), document.addEventListener("mousemove", this.handleMouseMove), document.addEventListener("mouseup", this.handleMouseUp));
149
+ },
150
+ beforeDestroy() {
151
+ window.removeEventListener("resize", this.handleResize), document.removeEventListener("touchmove", this.handleTouchMove), document.removeEventListener("mousemove", this.handleMouseMove), document.removeEventListener("mouseup", this.handleMouseUp);
152
+ },
153
+ methods: {
154
+ isWechatBrowser() {
155
+ return window.navigator.userAgent.toLowerCase().indexOf("micromessenger") !== -1;
156
+ },
157
+ isWechatMiniProgram() {
158
+ const e = window.navigator.userAgent.toLowerCase();
159
+ return window.__wxjs_environment === "miniprogram" ? !0 : e.indexOf("miniprogram") !== -1;
160
+ },
161
+ isWechatEnv() {
162
+ return this.isWechatBrowser() || this.isWechatMiniProgram();
163
+ },
164
+ getSysInfo() {
165
+ this.windowWidth = window.innerWidth, this.windowHeight = window.innerHeight, this.$nextTick(() => {
166
+ const e = this.$refs.movableView;
167
+ if (e) {
168
+ const t = e.getBoundingClientRect();
169
+ this.btnWidth = t.width || 50, this.btnHeight = t.height || 50, this.x = this.windowWidth - this.btnWidth - this.rightPx, this.y = this.windowHeight - this.btnHeight - this.bottomPx, this.oldX = this.x, this.oldY = this.y;
170
+ }
171
+ });
172
+ },
173
+ handleResize() {
174
+ this.getSysInfo();
175
+ },
176
+ // 触摸开始
177
+ touchstart(e) {
178
+ if (this.disabled) return;
179
+ this.isDragging = !0, this.isRemove = !0;
180
+ const t = e.touches[0], i = this.$refs.movableView.getBoundingClientRect();
181
+ this.startX = t.clientX - i.left, this.startY = t.clientY - i.top, this.$emit("dragStart");
182
+ },
183
+ // 触摸结束
184
+ touchend(e) {
185
+ if (!(this.disabled || !this.isDragging)) {
186
+ if (this.isDragging = !1, this.canDocking) {
187
+ const t = (this.windowWidth - this.btnWidth) / 2;
188
+ this.x < 0 || this.x > 0 && this.x <= t ? this.x = 20 : this.x = this.windowWidth - this.btnWidth - 20, this.oldX = this.x, this.oldY = this.y, this.$nextTick(() => {
189
+ this.isRemove = !1;
190
+ });
191
+ }
192
+ this.$emit("dragEnd");
193
+ }
194
+ },
195
+ // 触摸移动
196
+ handleTouchMove(e) {
197
+ if (!this.isDragging || this.disabled) return;
198
+ const t = e.touches[0];
199
+ let i = t.clientX - this.startX, s = t.clientY - this.startY;
200
+ i = Math.max(0, Math.min(i, this.windowWidth - this.btnWidth)), s = Math.max(0, Math.min(s, this.windowHeight - this.btnHeight)), this.x = i, this.y = s, this.oldX = i, this.oldY = s, this.$emit("dragging", { x: i, y: s }), e.preventDefault();
201
+ },
202
+ // 鼠标按下(支持PC)
203
+ handleMouseDown(e) {
204
+ if (this.disabled || e.button !== 0) return;
205
+ this.isDragging = !0, this.isRemove = !0;
206
+ const t = this.$refs.movableView.getBoundingClientRect();
207
+ this.startX = e.clientX - t.left, this.startY = e.clientY - t.top, this.$emit("dragStart"), e.preventDefault();
208
+ },
209
+ // 鼠标移动
210
+ handleMouseMove(e) {
211
+ if (!this.isDragging || this.disabled) return;
212
+ let t = e.clientX - this.startX, i = e.clientY - this.startY;
213
+ t = Math.max(0, Math.min(t, this.windowWidth - this.btnWidth)), i = Math.max(0, Math.min(i, this.windowHeight - this.btnHeight)), this.x = t, this.y = i, this.oldX = t, this.oldY = i, this.$emit("dragging", { x: t, y: i }), e.preventDefault();
214
+ },
215
+ // 鼠标释放
216
+ handleMouseUp(e) {
217
+ if (!(!this.isDragging || this.disabled)) {
218
+ if (this.isDragging = !1, this.canDocking) {
219
+ const t = (this.windowWidth - this.btnWidth) / 2;
220
+ this.x < 0 || this.x > 0 && this.x <= t ? this.x = 20 : this.x = this.windowWidth - this.btnWidth - 20, this.oldX = this.x, this.oldY = this.y, this.$nextTick(() => {
221
+ this.isRemove = !1;
222
+ });
223
+ }
224
+ this.$emit("dragEnd");
225
+ }
226
+ },
227
+ // 点击按钮
228
+ clickBtn(e) {
229
+ this.isDragging || window.$webc.getwechaturl();
230
+ }
231
+ }
232
+ };
233
+ function p(e, t, i, s, n, o) {
234
+ return n.isshow ? (l(), c("div", {
235
+ key: 0,
236
+ class: "movable-area",
237
+ style: a(o.areaStyle),
238
+ ref: "movableArea"
239
+ }, [
240
+ u("div", {
241
+ ref: "movableView",
242
+ style: a(o.viewStyle),
243
+ class: g({ "animation-info": !n.isRemove }),
244
+ onClick: t[0] || (t[0] = (...h) => o.clickBtn && o.clickBtn(...h)),
245
+ onTouchstart: t[1] || (t[1] = (...h) => o.touchstart && o.touchstart(...h)),
246
+ onTouchend: t[2] || (t[2] = (...h) => o.touchend && o.touchend(...h))
247
+ }, null, 38)
248
+ ], 4)) : m("", !0);
249
+ }
250
+ const r = /* @__PURE__ */ b(v, [["render", p], ["__scopeId", "data-v-1d2e65a3"]]), x = [r], d = function(e) {
251
+ x.forEach((t) => {
252
+ e.component(t.name, t);
253
+ });
254
+ };
255
+ typeof window < "u" && window.Vue && d(window.Vue);
256
+ const W = {
257
+ install: d,
258
+ WebcServiceBtn: r
259
+ };
260
+ export {
261
+ W as default
262
+ };
@@ -0,0 +1 @@
1
+ (function(s,r){typeof exports=="object"&&typeof module<"u"?module.exports=r(require("vue")):typeof define=="function"&&define.amd?define(["vue"],r):(s=typeof globalThis<"u"?globalThis:s||self,s.webcLib=r(s.Vue))})(this,function(s){"use strict";const r={isDev(){const e=window.location.hostname;return e==="localhost"||e==="127.0.0.1"||e.includes("192.168.")},getDynamic:e=>new Promise((t,i)=>{fetch(`${e}`).then(n=>n.json()).then(n=>{if(!n||n.ret_code!=="10000"&&n.code!==200){i(n);return}else localStorage.setItem("tenantConfigData",JSON.stringify(n.data||{})),t(n)}).catch(n=>{i(n)})}),isTMCUser(e){return e.includes(window.location.host)},getwechaturl(){const e=JSON.parse(localStorage.getItem("tenantConfigData")).wechaturl,t=document.createElement("a");t.href=e,t.target="_blank",document.body.appendChild(t),t.click(),document.body.removeChild(t)}};window.$webc=r;const c="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAD/klEQVR4nK2WUVLbSBCG//YuTyGFq0iq9g3lBDgnwJwg9gksnwDnBBEnwJwA+QSYEyCfAHMClLdULak1Fd7CMvlGso0wspGdfFUj9bTG0//0tEY2rYHr7n6Ss6acGpKjqU4DG9NPZbVE+uvC4m+pKlJJgOu+7+jxMZIUqAqmWNo6riLEaEtx4T+B3MO58tXmmI24JsrbFAukRz+mRXb2uOeYRRbfHmMtxWiluPB9Q+7xErNO8yMHrIoJv6VagQt3WwyO5Nw+XUzFFn/vYpVitBc8C276KtVaFv87ps8zsmL/HxAgUBFTYme3I6wMF76LGPMF0z9bKsJoz3BhUJf7cYNJcLuWtpsWp5NsZc6OGNHUcib8Jpb+PvWZYiEhCzmTx+yY7Yi0wEsBnd1zbi2e3ElvA3ncPb6VgReZ8EZ8JmsxmeiRiRN8RLNDRCQq8EwAihsovsL0T9qkPqV/Sa9OW59p6hGRIOIAR2KD20OezDHaHNIcU8UdlI5IYyj304vZLPgMRLCQUxbi56Jf+0hmxlgZRptD+h03721X2O/q+PlkvSwLplOy0sObMRfA6lus/hzPHYp7KD7D/aegJuwYASfYqWq1SO7NhS/uTAB7f0TASFm6bYynjh1oE0gxh1LCYnboPWEa4OtgTSGObR8aBdJE2SWe38f0lfQGzBkx5xc8q7Fa1wuoNrgK7DUChlhiS1NWvIe5HONs+CMCpnVDdceaUmnejQWQai5jLN+SxcPFkx3Z7ucN5nIqCzC75hqLgGXBlsHcY+bexyynkgCzC4K2sNaGOoipgw5mOdUEbH3wHxZtwOtz22cEFM7/Emzw3bhtxDMBpjuysYOV4/vaamSTM7DHNVKGRdg9Bu/Jw8FCdY+x1oZ5oycBta7kUkl97kEWnMyaSiArIVk5w+SHpCm+5UfrQw30WciReGs4HwIB35sb+iP6oaBUgAf1CeoPGJIsfkLLyP7I6D4sinWdd1dcGyziEH/CnE3mvPTZIKuxwGil5BP+SFnBDqPaKB7ixs/7rYe+pCv8CV/NBmd/g3Et+kw8GzcLplN8PVxeEH33gX6gKUsFeNiKBpMPmdzJ3n70Xy/cRf8eXT8LBbVwEvrVm7smWChAUA9BJ4xt4xviylgpwJNn4n7Ij//jjWjjmpMLcXWfXhXI9j47IfNAjAuzmjIN8IUq8KqAGaygyb+k1FeuXsFv02wcwf2nvk+kF8E9lQUs4oPIHvbktq9nW1MkE+x0oqwIn+pgkY0E5JO7c8w6bUJVH0pvUtn9PkFbPGvhD8TrJ1m4uEVFjLY2CBgS5BPmS7KCtERSf1XgGRsKoMj8ATPDbIS3jzGpErSI0dam8GYc5MG3W2V1UIVfwJ75zAMZtcIAAAAASUVORK5CYII=",u=(e,t)=>{const i=e.__vccOpts||e;for(const[o,n]of t)i[o]=n;return i},g={name:"WebcServiceBtn",props:{buttonText:{type:String,default:"拖动"},disabled:{type:Boolean,default:!1},canDocking:{type:Boolean,default:!0},bottomPx:{type:Number,default:200},rightPx:{type:Number,default:20},customStyle:{type:Object,default:()=>({})}},data(){return{isshow:!0,x:0,y:0,oldX:0,oldY:0,isRemove:!0,windowWidth:0,windowHeight:0,btnWidth:40,btnHeight:40,isDragging:!1,startX:0,startY:0}},computed:{areaStyle(){return{width:"100%",height:"100%",position:"fixed",top:"0",left:"0",right:"0",bottom:"0",zIndex:"9999",pointerEvents:"none"}},viewStyle(){return{...{width:this.btnWidth+"px",height:this.btnHeight+"px",backgroundImage:`url(${c})`,backgroundSize:"cover",backgroundPosition:"center",backgroundRepeat:"no-repeat",borderRadius:"50px",color:"#FFFFFF",fontSize:"18px",touchAction:"none",display:"flex",alignItems:"center",justifyContent:"center",position:"absolute",cursor:"pointer",pointerEvents:this.disabled?"none":"auto",willChange:"transform",transform:`translate(${this.x}px, ${this.y}px)`,transition:this.isRemove?"none":"transform 0.25s ease",userSelect:"none",WebkitUserSelect:"none",WebkitTapHighlightColor:"transparent",outline:"none"},...this.customStyle}}},created(){const e=localStorage.getItem("tenantConfigData"),t=e?JSON.parse(e):null;if(!(t!=null&&t.wechaturl)){this.isshow=!1;return}if(!this.isWechatEnv()){this.isshow=!1;return}},mounted(){this.isshow!=!1&&(this.getSysInfo(),window.addEventListener("resize",this.handleResize),document.addEventListener("touchmove",this.handleTouchMove,{passive:!1}),document.addEventListener("mousemove",this.handleMouseMove),document.addEventListener("mouseup",this.handleMouseUp))},beforeDestroy(){window.removeEventListener("resize",this.handleResize),document.removeEventListener("touchmove",this.handleTouchMove),document.removeEventListener("mousemove",this.handleMouseMove),document.removeEventListener("mouseup",this.handleMouseUp)},methods:{isWechatBrowser(){return window.navigator.userAgent.toLowerCase().indexOf("micromessenger")!==-1},isWechatMiniProgram(){const e=window.navigator.userAgent.toLowerCase();return window.__wxjs_environment==="miniprogram"?!0:e.indexOf("miniprogram")!==-1},isWechatEnv(){return this.isWechatBrowser()||this.isWechatMiniProgram()},getSysInfo(){this.windowWidth=window.innerWidth,this.windowHeight=window.innerHeight,this.$nextTick(()=>{const e=this.$refs.movableView;if(e){const t=e.getBoundingClientRect();this.btnWidth=t.width||50,this.btnHeight=t.height||50,this.x=this.windowWidth-this.btnWidth-this.rightPx,this.y=this.windowHeight-this.btnHeight-this.bottomPx,this.oldX=this.x,this.oldY=this.y}})},handleResize(){this.getSysInfo()},touchstart(e){if(this.disabled)return;this.isDragging=!0,this.isRemove=!0;const t=e.touches[0],i=this.$refs.movableView.getBoundingClientRect();this.startX=t.clientX-i.left,this.startY=t.clientY-i.top,this.$emit("dragStart")},touchend(e){if(!(this.disabled||!this.isDragging)){if(this.isDragging=!1,this.canDocking){const t=(this.windowWidth-this.btnWidth)/2;this.x<0||this.x>0&&this.x<=t?this.x=20:this.x=this.windowWidth-this.btnWidth-20,this.oldX=this.x,this.oldY=this.y,this.$nextTick(()=>{this.isRemove=!1})}this.$emit("dragEnd")}},handleTouchMove(e){if(!this.isDragging||this.disabled)return;const t=e.touches[0];let i=t.clientX-this.startX,o=t.clientY-this.startY;i=Math.max(0,Math.min(i,this.windowWidth-this.btnWidth)),o=Math.max(0,Math.min(o,this.windowHeight-this.btnHeight)),this.x=i,this.y=o,this.oldX=i,this.oldY=o,this.$emit("dragging",{x:i,y:o}),e.preventDefault()},handleMouseDown(e){if(this.disabled||e.button!==0)return;this.isDragging=!0,this.isRemove=!0;const t=this.$refs.movableView.getBoundingClientRect();this.startX=e.clientX-t.left,this.startY=e.clientY-t.top,this.$emit("dragStart"),e.preventDefault()},handleMouseMove(e){if(!this.isDragging||this.disabled)return;let t=e.clientX-this.startX,i=e.clientY-this.startY;t=Math.max(0,Math.min(t,this.windowWidth-this.btnWidth)),i=Math.max(0,Math.min(i,this.windowHeight-this.btnHeight)),this.x=t,this.y=i,this.oldX=t,this.oldY=i,this.$emit("dragging",{x:t,y:i}),e.preventDefault()},handleMouseUp(e){if(!(!this.isDragging||this.disabled)){if(this.isDragging=!1,this.canDocking){const t=(this.windowWidth-this.btnWidth)/2;this.x<0||this.x>0&&this.x<=t?this.x=20:this.x=this.windowWidth-this.btnWidth-20,this.oldX=this.x,this.oldY=this.y,this.$nextTick(()=>{this.isRemove=!1})}this.$emit("dragEnd")}},clickBtn(e){this.isDragging||window.$webc.getwechaturl()}}};function m(e,t,i,o,n,h){return n.isshow?(s.openBlock(),s.createElementBlock("div",{key:0,class:"movable-area",style:s.normalizeStyle(h.areaStyle),ref:"movableArea"},[s.createElementVNode("div",{ref:"movableView",style:s.normalizeStyle(h.viewStyle),class:s.normalizeClass({"animation-info":!n.isRemove}),onClick:t[0]||(t[0]=(...a)=>h.clickBtn&&h.clickBtn(...a)),onTouchstart:t[1]||(t[1]=(...a)=>h.touchstart&&h.touchstart(...a)),onTouchend:t[2]||(t[2]=(...a)=>h.touchend&&h.touchend(...a))},null,38)],4)):s.createCommentVNode("",!0)}const d=u(g,[["render",m],["__scopeId","data-v-1d2e65a3"]]),w=[d],l=function(e){w.forEach(t=>{e.component(t.name,t)})};return typeof window<"u"&&window.Vue&&l(window.Vue),{install:l,WebcServiceBtn:d}});
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@nj_wangrizhen/webc-lib",
3
+ "version": "1.0.3",
4
+ "type": "module",
5
+ "main": "./dist/webc-lib.umd.js",
6
+ "module": "./dist/webc-lib.es.js",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/webc-lib.es.js",
10
+ "require": "./dist/webc-lib.umd.js"
11
+ }
12
+ },
13
+ "peerDependencies": {
14
+ "vue": "^2 || ^3"
15
+ },
16
+ "devDependencies": {
17
+ "@vitejs/plugin-vue": "^5.0.0",
18
+ "vite": "^5.0.0",
19
+ "vue": "^3.4.0"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "src",
24
+ "README.md"
25
+ ],
26
+ "scripts": {
27
+ "dev:lib": "vite build --watch --mode lib",
28
+ "dev:demo": "vite --mode demo",
29
+ "build:lib": "vite build --mode lib"
30
+ }
31
+ }
Binary file
@@ -0,0 +1,334 @@
1
+ <template>
2
+ <template v-if="isshow">
3
+ <div
4
+ class="movable-area"
5
+ :style="areaStyle"
6
+ ref="movableArea"
7
+ >
8
+ <div
9
+ ref="movableView"
10
+ :style="viewStyle"
11
+ :class="{ 'animation-info': !isRemove }"
12
+ @click="clickBtn"
13
+ @touchstart="touchstart"
14
+ @touchend="touchend"
15
+ >
16
+ <!-- {{ buttonText }} -->
17
+ </div>
18
+ </div>
19
+ </template>
20
+ </template>
21
+
22
+ <script>
23
+ import serviceIcon from '../../assets/img/service.png';
24
+ export default {
25
+ name: 'WebcServiceBtn',
26
+ props: {
27
+ // 按钮文字
28
+ buttonText: {
29
+ type: String,
30
+ default: '拖动'
31
+ },
32
+ // 是否禁用拖动
33
+ disabled: {
34
+ type: Boolean,
35
+ default: false
36
+ },
37
+ // 是否自动停靠
38
+ canDocking: {
39
+ type: Boolean,
40
+ default: true
41
+ },
42
+ // 按钮默认位置离底部距离(px)
43
+ bottomPx: {
44
+ type: Number,
45
+ default: 200
46
+ },
47
+ // 按钮默认位置离右边距离(px)
48
+ rightPx: {
49
+ type: Number,
50
+ default: 20
51
+ },
52
+ // 自定义样式
53
+ customStyle: {
54
+ type: Object,
55
+ default: () => ({})
56
+ }
57
+ },
58
+ data() {
59
+ return {
60
+ isshow:true,
61
+ x: 0,
62
+ y: 0,
63
+ oldX: 0,
64
+ oldY: 0,
65
+ isRemove: true,
66
+ windowWidth: 0,
67
+ windowHeight: 0,
68
+ btnWidth: 40,
69
+ btnHeight: 40,
70
+ isDragging: false,
71
+ startX: 0,
72
+ startY: 0
73
+ };
74
+ },
75
+ computed: {
76
+ // 区域样式
77
+ areaStyle() {
78
+ return {
79
+ width: '100%',
80
+ height: '100%',
81
+ position: 'fixed',
82
+ top: '0',
83
+ left: '0',
84
+ right: '0',
85
+ bottom: '0',
86
+ zIndex: '9999',
87
+ pointerEvents: 'none'
88
+ };
89
+ },
90
+ // 按钮样式(完全内联)
91
+ viewStyle() {
92
+ const baseStyle = {
93
+ width: this.btnWidth + 'px',
94
+ height: this.btnHeight + 'px',
95
+ backgroundImage: `url(${serviceIcon})`,
96
+ backgroundSize: 'cover',
97
+ backgroundPosition: 'center',
98
+ backgroundRepeat: 'no-repeat',
99
+ borderRadius: '50px',
100
+ color: '#FFFFFF',
101
+ fontSize: '18px',
102
+ touchAction: 'none',
103
+ display: 'flex',
104
+ alignItems: 'center',
105
+ justifyContent: 'center',
106
+ position: 'absolute',
107
+ cursor: 'pointer',
108
+ pointerEvents: this.disabled ? 'none' : 'auto',
109
+ willChange: 'transform',
110
+ transform: `translate(${this.x}px, ${this.y}px)`,
111
+ transition: this.isRemove ? 'none' : 'transform 0.25s ease',
112
+ userSelect: 'none',
113
+ WebkitUserSelect: 'none',
114
+ // 👇 添加这两行,移除点击高亮
115
+ WebkitTapHighlightColor: 'transparent',
116
+ outline: 'none'
117
+ };
118
+
119
+ return { ...baseStyle, ...this.customStyle };
120
+ }
121
+ },
122
+ created(){
123
+ const tenantConfigData = localStorage.getItem('tenantConfigData');
124
+ const config = tenantConfigData ? JSON.parse(tenantConfigData) : null;
125
+ if (!config?.wechaturl) {
126
+ this.isshow = false
127
+ return
128
+ }
129
+ if(!this.isWechatEnv()){ //只在微信环境显示
130
+ this.isshow = false
131
+ return
132
+ }
133
+ },
134
+ mounted() {
135
+ if(this.isshow == false) return
136
+ this.getSysInfo();
137
+ window.addEventListener('resize', this.handleResize);
138
+ document.addEventListener('touchmove', this.handleTouchMove, { passive: false });
139
+ // 支持鼠标拖动
140
+ document.addEventListener('mousemove', this.handleMouseMove);
141
+ document.addEventListener('mouseup', this.handleMouseUp);
142
+ },
143
+ beforeDestroy() {
144
+ window.removeEventListener('resize', this.handleResize);
145
+ document.removeEventListener('touchmove', this.handleTouchMove);
146
+ document.removeEventListener('mousemove', this.handleMouseMove);
147
+ document.removeEventListener('mouseup', this.handleMouseUp);
148
+ },
149
+ methods: {
150
+ isWechatBrowser() {
151
+ const ua = window.navigator.userAgent.toLowerCase();
152
+ return ua.indexOf('micromessenger') !== -1;
153
+ },
154
+
155
+ isWechatMiniProgram() {
156
+ const ua = window.navigator.userAgent.toLowerCase();
157
+ if (window.__wxjs_environment === 'miniprogram') {
158
+ return true;
159
+ }
160
+ return ua.indexOf('miniprogram') !== -1;
161
+ },
162
+
163
+ isWechatEnv() {
164
+ return this.isWechatBrowser() || this.isWechatMiniProgram();
165
+ },
166
+ getSysInfo() {
167
+ this.windowWidth = window.innerWidth;
168
+ this.windowHeight = window.innerHeight;
169
+
170
+ this.$nextTick(() => {
171
+ const view = this.$refs.movableView;
172
+ if (view) {
173
+ // 获取实际尺寸
174
+ const rect = view.getBoundingClientRect();
175
+ this.btnWidth = rect.width || 50;
176
+ this.btnHeight = rect.height || 50;
177
+
178
+ this.x = this.windowWidth - this.btnWidth - this.rightPx;
179
+ this.y = this.windowHeight - this.btnHeight - this.bottomPx;
180
+ this.oldX = this.x;
181
+ this.oldY = this.y;
182
+ }
183
+ });
184
+ },
185
+ handleResize() {
186
+ this.getSysInfo();
187
+ },
188
+ // 触摸开始
189
+ touchstart(e) {
190
+ if (this.disabled) return;
191
+
192
+ this.isDragging = true;
193
+ this.isRemove = true;
194
+
195
+ const touch = e.touches[0];
196
+ const rect = this.$refs.movableView.getBoundingClientRect();
197
+ this.startX = touch.clientX - rect.left;
198
+ this.startY = touch.clientY - rect.top;
199
+
200
+ // 触发开始拖动事件
201
+ this.$emit('dragStart');
202
+ },
203
+ // 触摸结束
204
+ touchend(e) {
205
+ if (this.disabled || !this.isDragging) return;
206
+
207
+ this.isDragging = false;
208
+
209
+ if (this.canDocking) {
210
+ const halfWidth = (this.windowWidth - this.btnWidth) / 2;
211
+
212
+ if (this.x < 0 || (this.x > 0 && this.x <= halfWidth)) {
213
+ this.x = 20;
214
+ } else {
215
+ this.x = this.windowWidth - this.btnWidth - 20;
216
+ }
217
+
218
+ this.oldX = this.x;
219
+ this.oldY = this.y;
220
+
221
+ this.$nextTick(() => {
222
+ this.isRemove = false;
223
+ });
224
+ }
225
+
226
+ // 触发结束拖动事件
227
+ this.$emit('dragEnd');
228
+ },
229
+ // 触摸移动
230
+ handleTouchMove(e) {
231
+ if (!this.isDragging || this.disabled) return;
232
+
233
+ const touch = e.touches[0];
234
+ let newX = touch.clientX - this.startX;
235
+ let newY = touch.clientY - this.startY;
236
+
237
+ newX = Math.max(0, Math.min(newX, this.windowWidth - this.btnWidth));
238
+ newY = Math.max(0, Math.min(newY, this.windowHeight - this.btnHeight));
239
+
240
+ this.x = newX;
241
+ this.y = newY;
242
+ this.oldX = newX;
243
+ this.oldY = newY;
244
+
245
+ // 触发拖动中事件
246
+ this.$emit('dragging', { x: newX, y: newY });
247
+
248
+ e.preventDefault();
249
+ },
250
+ // 鼠标按下(支持PC)
251
+ handleMouseDown(e) {
252
+ if (this.disabled) return;
253
+ if (e.button !== 0) return; // 只响应左键
254
+
255
+ this.isDragging = true;
256
+ this.isRemove = true;
257
+
258
+ const rect = this.$refs.movableView.getBoundingClientRect();
259
+ this.startX = e.clientX - rect.left;
260
+ this.startY = e.clientY - rect.top;
261
+
262
+ this.$emit('dragStart');
263
+ e.preventDefault();
264
+ },
265
+ // 鼠标移动
266
+ handleMouseMove(e) {
267
+ if (!this.isDragging || this.disabled) return;
268
+
269
+ let newX = e.clientX - this.startX;
270
+ let newY = e.clientY - this.startY;
271
+
272
+ newX = Math.max(0, Math.min(newX, this.windowWidth - this.btnWidth));
273
+ newY = Math.max(0, Math.min(newY, this.windowHeight - this.btnHeight));
274
+
275
+ this.x = newX;
276
+ this.y = newY;
277
+ this.oldX = newX;
278
+ this.oldY = newY;
279
+
280
+ this.$emit('dragging', { x: newX, y: newY });
281
+
282
+ e.preventDefault();
283
+ },
284
+ // 鼠标释放
285
+ handleMouseUp(e) {
286
+ if (!this.isDragging || this.disabled) return;
287
+
288
+ this.isDragging = false;
289
+
290
+ if (this.canDocking) {
291
+ const halfWidth = (this.windowWidth - this.btnWidth) / 2;
292
+
293
+ if (this.x < 0 || (this.x > 0 && this.x <= halfWidth)) {
294
+ this.x = 20;
295
+ } else {
296
+ this.x = this.windowWidth - this.btnWidth - 20;
297
+ }
298
+
299
+ this.oldX = this.x;
300
+ this.oldY = this.y;
301
+
302
+ this.$nextTick(() => {
303
+ this.isRemove = false;
304
+ });
305
+ }
306
+
307
+ this.$emit('dragEnd');
308
+ },
309
+ // 点击按钮
310
+ clickBtn(e) {
311
+ // 如果正在拖动则不触发点击
312
+ if (this.isDragging) return;
313
+ window.$webc.getwechaturl()
314
+ }
315
+ }
316
+ };
317
+ </script>
318
+
319
+ <style scoped>
320
+ .movable-area {
321
+ /* 所有样式都在内联中定义,这里只保留动画类 */
322
+ }
323
+
324
+ /* 移除所有点击效果 */
325
+ .movable-view {
326
+ -webkit-tap-highlight-color: transparent !important;
327
+ outline: none !important;
328
+ }
329
+
330
+ /* 移除点击时的阴影变化 */
331
+ .movable-view:active {
332
+ box-shadow: 0px 4px 12px 0px rgb(25, 104, 252) !important;
333
+ }
334
+ </style>
package/src/index.js ADDED
@@ -0,0 +1,24 @@
1
+ // 1. 引入工具,自动执行 window.$webc 挂载
2
+ import './utils/webcommon.js'
3
+
4
+ import WebcServiceBtn from './components/WebcServiceBtn/index.vue'
5
+
6
+ // 组件集合
7
+ const components = [WebcServiceBtn]
8
+
9
+ // 安装方法,Vue.use(包) 自动全局注册所有组件
10
+ const install = function (Vue) {
11
+ components.forEach(comp => {
12
+ Vue.component(comp.name, comp)
13
+ })
14
+ }
15
+
16
+ // 兼容Vue2/Vue3自动注册
17
+ if (typeof window !== 'undefined' && window.Vue) {
18
+ install(window.Vue)
19
+ }
20
+
21
+ export default {
22
+ install,
23
+ WebcServiceBtn
24
+ }
@@ -0,0 +1,50 @@
1
+ // src/utils/webcommon.js
2
+ const webc = {
3
+ // 环境判断方法
4
+ isDev() {
5
+ const host = window.location.hostname
6
+ return host === 'localhost' || host === '127.0.0.1' || host.includes('192.168.')
7
+ },
8
+ /**
9
+ * 获取公共企业设置
10
+ */
11
+ getDynamic:(url) => {
12
+ return new Promise((resolve, reject)=>{
13
+ const baseUrl = ''
14
+ fetch(`${baseUrl}${url}`).then(res => {
15
+ return res.json();
16
+ }).then((res)=>{
17
+ if (!res || (res.ret_code !== '10000' && res.code !== 200)){
18
+ reject(res)
19
+ return
20
+ }else{
21
+ localStorage.setItem('tenantConfigData', JSON.stringify(res.data || {}))
22
+ resolve(res)
23
+ }
24
+ }).catch((err)=>{
25
+ reject(err)
26
+ })
27
+ })
28
+ },
29
+ /**
30
+ * 判断 当前 URL 是否 是 tmc 用户
31
+ * @returns {boolean} 是否为 tmc 用户
32
+ */
33
+ isTMCUser(urllist) {
34
+ return urllist.includes(window.location.host)
35
+ },
36
+ getwechaturl(){
37
+ const kfUrl = JSON.parse(localStorage.getItem('tenantConfigData')).wechaturl;
38
+ const a = document.createElement('a');
39
+ a.href = kfUrl;
40
+ a.target = '_blank';
41
+ document.body.appendChild(a);
42
+ a.click();
43
+ document.body.removeChild(a);
44
+ }
45
+ }
46
+
47
+ // 关键:导入包时自动挂载到window
48
+ window.$webc = webc
49
+
50
+ export default webc