@cnc_cbz/usefultools-plugin-official 1.0.1

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.
@@ -0,0 +1,286 @@
1
+ import { defineComponent, ref, computed, watch, openBlock, createElementBlock, createCommentVNode, createElementVNode, withDirectives, vModelText, toDisplayString, normalizeClass, createTextVNode, Fragment, renderList, vModelCheckbox } from "vue";
2
+ const _hoisted_1 = { class: "flex flex-col h-full gap-5" };
3
+ const _hoisted_2 = { class: "flex items-center gap-4" };
4
+ const _hoisted_3 = { class: "flex items-center gap-2" };
5
+ const _hoisted_4 = { class: "flex-1 h-12 bg-deep-charcoal border-4 border-black rounded-xl flex items-center px-4 shadow-hard font-mono text-lg text-gray-300" };
6
+ const _hoisted_5 = { class: "material-icons text-lg" };
7
+ const _hoisted_6 = { class: "bg-deep-charcoal border-4 border-black rounded-xl shadow-hard overflow-hidden" };
8
+ const _hoisted_7 = { class: "grid grid-cols-4 border-b-2 border-black" };
9
+ const _hoisted_8 = { class: "p-3 flex items-center gap-2" };
10
+ const _hoisted_9 = { class: "material-icons text-base text-primary" };
11
+ const _hoisted_10 = { class: "text-sm font-bold text-white" };
12
+ const _hoisted_11 = { class: "ml-auto text-lg font-black text-primary" };
13
+ const _hoisted_12 = { class: "relative cursor-pointer" };
14
+ const _hoisted_13 = ["onUpdate:modelValue"];
15
+ const _hoisted_14 = { class: "flex flex-wrap gap-2" };
16
+ const _hoisted_15 = ["onClick"];
17
+ const _hoisted_16 = { class: "font-black" };
18
+ const _hoisted_17 = { class: "ml-1.5 text-xs opacity-70" };
19
+ const _sfc_main = /* @__PURE__ */ defineComponent({
20
+ __name: "index",
21
+ setup(__props) {
22
+ const roles = ["所有者", "组", "其他"];
23
+ const permBits = ["读取 (r)", "写入 (w)", "执行 (x)"];
24
+ const bitValues = [4, 2, 1];
25
+ const perms = ref([
26
+ [true, true, true],
27
+ // owner: rwx = 7
28
+ [true, false, true],
29
+ // group: r-x = 5
30
+ [true, false, true]
31
+ // other: r-x = 5
32
+ ]);
33
+ const octalInput = ref("755");
34
+ const symbolicInput = ref("");
35
+ const syncing = ref(false);
36
+ const octalFromPerms = computed(
37
+ () => perms.value.map(
38
+ (role) => role.reduce((sum, on, i) => sum + (on ? bitValues[i] : 0), 0)
39
+ ).join("")
40
+ );
41
+ const symbolicFromPerms = computed(
42
+ () => perms.value.map(
43
+ (role) => role.map((on, i) => on ? "rwx"[i] : "-").join("")
44
+ ).join("")
45
+ );
46
+ const lsStyle = computed(() => "-" + symbolicFromPerms.value);
47
+ watch(perms, () => {
48
+ if (syncing.value) return;
49
+ syncing.value = true;
50
+ octalInput.value = octalFromPerms.value;
51
+ symbolicInput.value = symbolicFromPerms.value;
52
+ syncing.value = false;
53
+ }, { deep: true });
54
+ watch(octalInput, (val) => {
55
+ if (syncing.value) return;
56
+ if (!/^[0-7]{3}$/.test(val)) return;
57
+ syncing.value = true;
58
+ const digits = val.split("").map(Number);
59
+ perms.value = digits.map(
60
+ (d) => bitValues.map((b) => (d & b) !== 0)
61
+ );
62
+ symbolicInput.value = symbolicFromPerms.value;
63
+ syncing.value = false;
64
+ });
65
+ const presets = [
66
+ { label: "755", desc: "标准目录/可执行文件" },
67
+ { label: "644", desc: "标准文件" },
68
+ { label: "777", desc: "完全开放" },
69
+ { label: "700", desc: "仅所有者" },
70
+ { label: "600", desc: "仅所有者读写" },
71
+ { label: "444", desc: "只读" }
72
+ ];
73
+ function applyPreset(octal) {
74
+ octalInput.value = octal;
75
+ }
76
+ const copySuccess = ref(false);
77
+ async function copyCommand() {
78
+ await navigator.clipboard.writeText(`chmod ${octalInput.value}`);
79
+ copySuccess.value = true;
80
+ setTimeout(() => {
81
+ copySuccess.value = false;
82
+ }, 1500);
83
+ }
84
+ return (_ctx, _cache) => {
85
+ return openBlock(), createElementBlock("div", _hoisted_1, [
86
+ createCommentVNode(" 八进制输入 + 命令复制 "),
87
+ createElementVNode("div", _hoisted_2, [
88
+ createElementVNode("div", _hoisted_3, [
89
+ _cache[1] || (_cache[1] = createElementVNode(
90
+ "span",
91
+ { class: "text-sm font-bold text-gray-400 uppercase tracking-wider" },
92
+ "chmod",
93
+ -1
94
+ /* CACHED */
95
+ )),
96
+ withDirectives(createElementVNode(
97
+ "input",
98
+ {
99
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => octalInput.value = $event),
100
+ maxlength: "3",
101
+ class: "w-24 h-12 bg-deep-charcoal text-center text-3xl font-black text-primary border-4 border-black rounded-xl outline-none focus:border-primary shadow-hard transition-all tracking-widest"
102
+ },
103
+ null,
104
+ 512
105
+ /* NEED_PATCH */
106
+ ), [
107
+ [vModelText, octalInput.value]
108
+ ])
109
+ ]),
110
+ createElementVNode(
111
+ "div",
112
+ _hoisted_4,
113
+ toDisplayString(lsStyle.value),
114
+ 1
115
+ /* TEXT */
116
+ ),
117
+ createElementVNode(
118
+ "button",
119
+ {
120
+ class: normalizeClass(["h-12 px-5 font-bold border-2 border-black rounded-xl shadow-hard-sm hover:shadow-none hover:translate-x-0.5 hover:translate-y-0.5 transition-all flex items-center gap-2 text-sm", copySuccess.value ? "bg-neon-green text-black" : "bg-primary text-black"]),
121
+ onClick: copyCommand
122
+ },
123
+ [
124
+ createElementVNode(
125
+ "span",
126
+ _hoisted_5,
127
+ toDisplayString(copySuccess.value ? "check" : "content_copy"),
128
+ 1
129
+ /* TEXT */
130
+ ),
131
+ createTextVNode(
132
+ " " + toDisplayString(copySuccess.value ? "已复制" : "复制命令"),
133
+ 1
134
+ /* TEXT */
135
+ )
136
+ ],
137
+ 2
138
+ /* CLASS */
139
+ )
140
+ ]),
141
+ createCommentVNode(" 权限矩阵 "),
142
+ createElementVNode("div", _hoisted_6, [
143
+ createCommentVNode(" 表头 "),
144
+ createElementVNode("div", _hoisted_7, [
145
+ _cache[2] || (_cache[2] = createElementVNode(
146
+ "div",
147
+ { class: "p-3" },
148
+ null,
149
+ -1
150
+ /* CACHED */
151
+ )),
152
+ (openBlock(), createElementBlock(
153
+ Fragment,
154
+ null,
155
+ renderList(permBits, (perm) => {
156
+ return createElementVNode(
157
+ "div",
158
+ {
159
+ key: perm,
160
+ class: "p-3 text-center text-xs font-bold text-gray-400 uppercase tracking-wider"
161
+ },
162
+ toDisplayString(perm),
163
+ 1
164
+ /* TEXT */
165
+ );
166
+ }),
167
+ 64
168
+ /* STABLE_FRAGMENT */
169
+ ))
170
+ ]),
171
+ createCommentVNode(" 每行一个角色 "),
172
+ (openBlock(), createElementBlock(
173
+ Fragment,
174
+ null,
175
+ renderList(roles, (role, ri) => {
176
+ return createElementVNode("div", {
177
+ key: role,
178
+ class: "grid grid-cols-4 border-b border-white/5 last:border-b-0 hover:bg-white/5 transition-colors"
179
+ }, [
180
+ createElementVNode("div", _hoisted_8, [
181
+ createElementVNode(
182
+ "span",
183
+ _hoisted_9,
184
+ toDisplayString(ri === 0 ? "person" : ri === 1 ? "group" : "public"),
185
+ 1
186
+ /* TEXT */
187
+ ),
188
+ createElementVNode(
189
+ "span",
190
+ _hoisted_10,
191
+ toDisplayString(role),
192
+ 1
193
+ /* TEXT */
194
+ ),
195
+ createElementVNode(
196
+ "span",
197
+ _hoisted_11,
198
+ toDisplayString(octalInput.value[ri] || "0"),
199
+ 1
200
+ /* TEXT */
201
+ )
202
+ ]),
203
+ (openBlock(), createElementBlock(
204
+ Fragment,
205
+ null,
206
+ renderList(permBits, (_, pi) => {
207
+ return createElementVNode("div", {
208
+ key: pi,
209
+ class: "p-3 flex items-center justify-center"
210
+ }, [
211
+ createElementVNode("label", _hoisted_12, [
212
+ withDirectives(createElementVNode("input", {
213
+ "onUpdate:modelValue": ($event) => perms.value[ri][pi] = $event,
214
+ type: "checkbox",
215
+ class: "sr-only peer"
216
+ }, null, 8, _hoisted_13), [
217
+ [vModelCheckbox, perms.value[ri][pi]]
218
+ ]),
219
+ _cache[3] || (_cache[3] = createElementVNode(
220
+ "div",
221
+ { class: "w-10 h-10 rounded-lg border-2 border-black bg-white/5 peer-checked:bg-primary peer-checked:border-primary flex items-center justify-center transition-all" },
222
+ [
223
+ createElementVNode("span", { class: "material-icons text-xl text-transparent peer-checked:text-black transition-colors" }, "check")
224
+ ],
225
+ -1
226
+ /* CACHED */
227
+ ))
228
+ ])
229
+ ]);
230
+ }),
231
+ 64
232
+ /* STABLE_FRAGMENT */
233
+ ))
234
+ ]);
235
+ }),
236
+ 64
237
+ /* STABLE_FRAGMENT */
238
+ ))
239
+ ]),
240
+ createCommentVNode(" 常用预设 "),
241
+ createElementVNode("div", null, [
242
+ _cache[4] || (_cache[4] = createElementVNode(
243
+ "span",
244
+ { class: "text-xs font-bold text-gray-500 uppercase tracking-wider mb-2 block" },
245
+ "常用预设",
246
+ -1
247
+ /* CACHED */
248
+ )),
249
+ createElementVNode("div", _hoisted_14, [
250
+ (openBlock(), createElementBlock(
251
+ Fragment,
252
+ null,
253
+ renderList(presets, (p) => {
254
+ return createElementVNode("button", {
255
+ key: p.label,
256
+ class: normalizeClass(["px-3 py-2 border-2 border-black rounded-lg font-bold text-sm transition-all", octalInput.value === p.label ? "bg-primary text-black shadow-hard-sm" : "bg-white/5 text-gray-300 hover:bg-white/10 hover:text-white"]),
257
+ onClick: ($event) => applyPreset(p.label)
258
+ }, [
259
+ createElementVNode(
260
+ "span",
261
+ _hoisted_16,
262
+ toDisplayString(p.label),
263
+ 1
264
+ /* TEXT */
265
+ ),
266
+ createElementVNode(
267
+ "span",
268
+ _hoisted_17,
269
+ toDisplayString(p.desc),
270
+ 1
271
+ /* TEXT */
272
+ )
273
+ ], 10, _hoisted_15);
274
+ }),
275
+ 64
276
+ /* STABLE_FRAGMENT */
277
+ ))
278
+ ])
279
+ ])
280
+ ]);
281
+ };
282
+ }
283
+ });
284
+ export {
285
+ _sfc_main as default
286
+ };
@@ -0,0 +1,211 @@
1
+ import { defineComponent, ref, computed, openBlock, createElementBlock, createCommentVNode, createElementVNode, withDirectives, vModelText, normalizeStyle, Fragment, renderList, toDisplayString, normalizeClass, createTextVNode } from "vue";
2
+ const _hoisted_1 = { class: "flex flex-col h-full gap-5" };
3
+ const _hoisted_2 = { class: "bg-deep-charcoal border-4 border-black rounded-xl p-4 shadow-hard" };
4
+ const _hoisted_3 = { class: "flex flex-wrap items-center gap-4" };
5
+ const _hoisted_4 = ["value"];
6
+ const _hoisted_5 = { class: "flex flex-wrap gap-2 mt-3" };
7
+ const _hoisted_6 = ["onClick"];
8
+ const _hoisted_7 = {
9
+ key: 0,
10
+ class: "flex-1 grid grid-cols-1 lg:grid-cols-2 gap-4 min-h-0"
11
+ };
12
+ const _hoisted_8 = ["onClick"];
13
+ const _hoisted_9 = { class: "flex items-center justify-between mb-2" };
14
+ const _hoisted_10 = { class: "text-xs font-bold text-gray-500 uppercase tracking-wider" };
15
+ const _hoisted_11 = {
16
+ key: 1,
17
+ class: "px-4 py-2 bg-coral-red/20 border-2 border-coral-red rounded flex items-center gap-2 text-coral-red font-bold text-sm"
18
+ };
19
+ const _sfc_main = /* @__PURE__ */ defineComponent({
20
+ __name: "index",
21
+ setup(__props) {
22
+ const hexInput = ref("#3b82f6");
23
+ const copyField = ref("");
24
+ function hexToRgb(hex) {
25
+ const m = hex.replace("#", "").match(/^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);
26
+ if (!m) {
27
+ const s = hex.replace("#", "").match(/^([0-9a-f])([0-9a-f])([0-9a-f])$/i);
28
+ if (!s) return null;
29
+ return [parseInt(s[1] + s[1], 16), parseInt(s[2] + s[2], 16), parseInt(s[3] + s[3], 16)];
30
+ }
31
+ return [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16)];
32
+ }
33
+ function rgbToHsl(r, g, b) {
34
+ r /= 255;
35
+ g /= 255;
36
+ b /= 255;
37
+ const max = Math.max(r, g, b), min = Math.min(r, g, b);
38
+ let h = 0, s = 0;
39
+ const l = (max + min) / 2;
40
+ if (max !== min) {
41
+ const d = max - min;
42
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
43
+ if (max === r) h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
44
+ else if (max === g) h = ((b - r) / d + 2) / 6;
45
+ else h = ((r - g) / d + 4) / 6;
46
+ }
47
+ return [Math.round(h * 360), Math.round(s * 100), Math.round(l * 100)];
48
+ }
49
+ const rgb = computed(() => hexToRgb(hexInput.value));
50
+ const hsl = computed(() => rgb.value ? rgbToHsl(...rgb.value) : null);
51
+ const formats = computed(() => {
52
+ if (!rgb.value || !hsl.value) return [];
53
+ const [r, g, b] = rgb.value;
54
+ const [h, s, l] = hsl.value;
55
+ const hex = `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
56
+ return [
57
+ { label: "HEX", value: hex.toUpperCase(), color: "text-primary" },
58
+ { label: "RGB", value: `rgb(${r}, ${g}, ${b})`, color: "text-electric-blue" },
59
+ { label: "HSL", value: `hsl(${h}, ${s}%, ${l}%)`, color: "text-vibrant-purple" },
60
+ { label: "RGB 数值", value: `${r}, ${g}, ${b}`, color: "text-neon-green" }
61
+ ];
62
+ });
63
+ const presets = [
64
+ "#ef4444",
65
+ "#f97316",
66
+ "#f9b11f",
67
+ "#84cc16",
68
+ "#22c55e",
69
+ "#06b6d4",
70
+ "#3b82f6",
71
+ "#8b5cf6",
72
+ "#ec4899",
73
+ "#ffffff",
74
+ "#000000",
75
+ "#6b7280"
76
+ ];
77
+ async function copy(text, field) {
78
+ await navigator.clipboard.writeText(text);
79
+ copyField.value = field;
80
+ setTimeout(() => {
81
+ copyField.value = "";
82
+ }, 1200);
83
+ }
84
+ return (_ctx, _cache) => {
85
+ return openBlock(), createElementBlock("div", _hoisted_1, [
86
+ createCommentVNode(" 输入 + 预览 "),
87
+ createElementVNode("div", _hoisted_2, [
88
+ _cache[2] || (_cache[2] = createElementVNode(
89
+ "div",
90
+ { class: "flex items-center gap-2 mb-3" },
91
+ [
92
+ createElementVNode("span", { class: "material-icons text-primary text-lg" }, "palette"),
93
+ createElementVNode("span", { class: "text-sm font-bold text-gray-400 uppercase tracking-wider" }, "颜色转换器")
94
+ ],
95
+ -1
96
+ /* CACHED */
97
+ )),
98
+ createElementVNode("div", _hoisted_3, [
99
+ createElementVNode("input", {
100
+ type: "color",
101
+ value: hexInput.value,
102
+ onInput: _cache[0] || (_cache[0] = ($event) => hexInput.value = $event.target.value),
103
+ class: "w-16 h-16 border-4 border-black rounded-lg cursor-pointer shadow-hard"
104
+ }, null, 40, _hoisted_4),
105
+ withDirectives(createElementVNode(
106
+ "input",
107
+ {
108
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => hexInput.value = $event),
109
+ placeholder: "#3b82f6",
110
+ class: "flex-1 h-12 bg-bg-dark text-gray-100 border-4 border-black rounded-lg px-4 font-mono text-lg shadow-hard focus:border-primary focus:shadow-none focus:translate-x-[4px] focus:translate-y-[4px] transition-all outline-none placeholder-gray-600"
111
+ },
112
+ null,
113
+ 512
114
+ /* NEED_PATCH */
115
+ ), [
116
+ [vModelText, hexInput.value]
117
+ ]),
118
+ createElementVNode(
119
+ "div",
120
+ {
121
+ class: "w-24 h-16 border-4 border-black rounded-lg shadow-hard",
122
+ style: normalizeStyle({ backgroundColor: hexInput.value })
123
+ },
124
+ null,
125
+ 4
126
+ /* STYLE */
127
+ )
128
+ ]),
129
+ createCommentVNode(" 预设色板 "),
130
+ createElementVNode("div", _hoisted_5, [
131
+ (openBlock(), createElementBlock(
132
+ Fragment,
133
+ null,
134
+ renderList(presets, (c) => {
135
+ return createElementVNode("button", {
136
+ key: c,
137
+ onClick: ($event) => hexInput.value = c,
138
+ class: "w-8 h-8 border-2 border-black rounded hover:scale-110 transition-transform",
139
+ style: normalizeStyle({ backgroundColor: c })
140
+ }, null, 12, _hoisted_6);
141
+ }),
142
+ 64
143
+ /* STABLE_FRAGMENT */
144
+ ))
145
+ ])
146
+ ]),
147
+ createCommentVNode(" 格式输出 "),
148
+ formats.value.length ? (openBlock(), createElementBlock("div", _hoisted_7, [
149
+ (openBlock(true), createElementBlock(
150
+ Fragment,
151
+ null,
152
+ renderList(formats.value, (f) => {
153
+ return openBlock(), createElementBlock("div", {
154
+ key: f.label,
155
+ class: "bg-deep-charcoal border-4 border-black rounded-xl p-4 shadow-hard cursor-pointer hover:border-primary transition-all group",
156
+ onClick: ($event) => copy(f.value, f.label)
157
+ }, [
158
+ createElementVNode("div", _hoisted_9, [
159
+ createElementVNode(
160
+ "span",
161
+ _hoisted_10,
162
+ toDisplayString(f.label),
163
+ 1
164
+ /* TEXT */
165
+ ),
166
+ createElementVNode(
167
+ "span",
168
+ {
169
+ class: normalizeClass(["material-icons text-sm opacity-0 group-hover:opacity-100 transition-opacity", copyField.value === f.label ? "text-neon-green" : "text-gray-500"])
170
+ },
171
+ toDisplayString(copyField.value === f.label ? "check" : "content_copy"),
172
+ 3
173
+ /* TEXT, CLASS */
174
+ )
175
+ ]),
176
+ createElementVNode(
177
+ "div",
178
+ {
179
+ class: normalizeClass(["font-mono text-lg select-all", f.color])
180
+ },
181
+ toDisplayString(f.value),
182
+ 3
183
+ /* TEXT, CLASS */
184
+ )
185
+ ], 8, _hoisted_8);
186
+ }),
187
+ 128
188
+ /* KEYED_FRAGMENT */
189
+ ))
190
+ ])) : createCommentVNode("v-if", true),
191
+ !rgb.value ? (openBlock(), createElementBlock("div", _hoisted_11, [..._cache[3] || (_cache[3] = [
192
+ createElementVNode(
193
+ "span",
194
+ { class: "material-icons text-lg" },
195
+ "error_outline",
196
+ -1
197
+ /* CACHED */
198
+ ),
199
+ createTextVNode(
200
+ " 无效的颜色值 ",
201
+ -1
202
+ /* CACHED */
203
+ )
204
+ ])])) : createCommentVNode("v-if", true)
205
+ ]);
206
+ };
207
+ }
208
+ });
209
+ export {
210
+ _sfc_main as default
211
+ };