@ysgroup/ui 0.1.26 → 0.1.29
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/package.json
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { CircleCheckFilled } from "@element-plus/icons-vue";
|
|
3
|
+
|
|
4
|
+
defineProps<{
|
|
5
|
+
value: unknown;
|
|
6
|
+
onLabel?: string;
|
|
7
|
+
offLabel?: string;
|
|
8
|
+
}>();
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<el-icon class="ys-bool-mark" :class="value ? 'is-yes' : 'is-no'" :size="18" :title="value ? (onLabel ?? '是') : (offLabel ?? '否')">
|
|
13
|
+
<CircleCheckFilled v-if="value" />
|
|
14
|
+
<svg v-else viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
|
|
15
|
+
<circle cx="512" cy="512" r="384" fill="none" stroke="currentColor" stroke-width="80" />
|
|
16
|
+
</svg>
|
|
17
|
+
</el-icon>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<style scoped>
|
|
21
|
+
.ys-bool-mark {
|
|
22
|
+
vertical-align: middle;
|
|
23
|
+
}
|
|
24
|
+
.ys-bool-mark.is-yes {
|
|
25
|
+
color: #5bb07a;
|
|
26
|
+
}
|
|
27
|
+
.ys-bool-mark.is-no {
|
|
28
|
+
color: #e6e9f0;
|
|
29
|
+
}
|
|
30
|
+
</style>
|
|
@@ -6,6 +6,7 @@ import { computed, ref, watch } from "vue";
|
|
|
6
6
|
import { FIELD_SPECS, ENUM_META } from "@ysgroup/contracts";
|
|
7
7
|
import { enumLabel } from "../tokens-runtime";
|
|
8
8
|
import { columnWidth as lookupColumnWidth } from "../columnWidths";
|
|
9
|
+
import YsBoolMark from "./YsBoolMark.vue";
|
|
9
10
|
import YsFormDialog from "./YsFormDialog.vue";
|
|
10
11
|
import YsRowActionMenu from "./YsRowActionMenu.vue";
|
|
11
12
|
import YsTableToolbar from "./YsTableToolbar.vue";
|
|
@@ -86,9 +87,17 @@ const paged = computed(() => {
|
|
|
86
87
|
return filtered.value.slice(start, start + pageSize.value);
|
|
87
88
|
});
|
|
88
89
|
|
|
90
|
+
function switchLabels(field: FieldSpec): { on: string; off: string } {
|
|
91
|
+
if (field.key === "enabled") return { on: "启用", off: "停用" };
|
|
92
|
+
return { on: "是", off: "否" };
|
|
93
|
+
}
|
|
94
|
+
|
|
89
95
|
function display(row: Record<string, unknown>, f: FieldSpec): string {
|
|
90
96
|
const v = props.rowDisplay ? props.rowDisplay(row, f.key, row[f.key]) : row[f.key];
|
|
91
|
-
if (f.widget === "switch")
|
|
97
|
+
if (f.widget === "switch") {
|
|
98
|
+
const labels = switchLabels(f);
|
|
99
|
+
return v ? labels.on : labels.off;
|
|
100
|
+
}
|
|
92
101
|
if (f.widget === "enum" && f.enum && ENUM_META[f.enum as keyof typeof ENUM_META]) {
|
|
93
102
|
return enumLabel(f.enum as keyof typeof ENUM_META, String(v ?? ""));
|
|
94
103
|
}
|
|
@@ -131,8 +140,18 @@ function onSubmit(payload: Record<string, unknown>) {
|
|
|
131
140
|
</YsTableToolbar>
|
|
132
141
|
|
|
133
142
|
<el-table :fit="false" :data="paged" v-loading="loading" stripe border size="small" table-layout="fixed" row-key="_id">
|
|
134
|
-
<el-table-column
|
|
135
|
-
|
|
143
|
+
<el-table-column
|
|
144
|
+
v-for="c in displayColumns"
|
|
145
|
+
:key="c.key"
|
|
146
|
+
:label="c.title"
|
|
147
|
+
:width="columnWidth(c)"
|
|
148
|
+
:show-overflow-tooltip="c.widget !== 'switch'"
|
|
149
|
+
:align="c.widget === 'switch' ? 'center' : undefined"
|
|
150
|
+
>
|
|
151
|
+
<template #default="{ row }">
|
|
152
|
+
<YsBoolMark v-if="c.widget === 'switch'" :value="row[c.key]" :on-label="switchLabels(c).on" :off-label="switchLabels(c).off" />
|
|
153
|
+
<slot v-else name="cell" :row="row" :column="c" :text="display(row, c)">{{ display(row, c) }}</slot>
|
|
154
|
+
</template>
|
|
136
155
|
</el-table-column>
|
|
137
156
|
<el-table-column v-if="!readonly" label="操作栏" :width="actionWidth ?? 76" fixed="right" align="center">
|
|
138
157
|
<template #default="{ row }">
|
|
@@ -176,6 +176,29 @@ function submit() {
|
|
|
176
176
|
type="textarea"
|
|
177
177
|
:rows="3"
|
|
178
178
|
/>
|
|
179
|
+
<el-date-picker
|
|
180
|
+
v-else-if="f.widget === 'datetime'"
|
|
181
|
+
v-model="form[f.key] as string"
|
|
182
|
+
type="datetime"
|
|
183
|
+
value-format="YYYY-MM-DD HH:mm:ss"
|
|
184
|
+
format="YYYY-MM-DD HH:mm:ss"
|
|
185
|
+
style="width: 100%"
|
|
186
|
+
/>
|
|
187
|
+
<el-date-picker
|
|
188
|
+
v-else-if="f.widget === 'date'"
|
|
189
|
+
v-model="form[f.key] as string"
|
|
190
|
+
type="date"
|
|
191
|
+
value-format="YYYY-MM-DD"
|
|
192
|
+
format="YYYY-MM-DD"
|
|
193
|
+
style="width: 100%"
|
|
194
|
+
/>
|
|
195
|
+
<el-time-picker
|
|
196
|
+
v-else-if="f.widget === 'time'"
|
|
197
|
+
v-model="form[f.key] as string"
|
|
198
|
+
value-format="HH:mm:ss"
|
|
199
|
+
format="HH:mm:ss"
|
|
200
|
+
style="width: 100%"
|
|
201
|
+
/>
|
|
179
202
|
<el-input v-else v-model="form[f.key] as string" />
|
|
180
203
|
</el-form-item>
|
|
181
204
|
</el-form>
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
<!-- YsLoginPage ——
|
|
1
|
+
<!-- YsLoginPage —— 统一登录页。口令由 @ysgroup/core 密封后提交。 -->
|
|
2
2
|
<script setup lang="ts">
|
|
3
3
|
import { ref } from "vue";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
defineProps<{
|
|
6
6
|
appTitle: string;
|
|
7
7
|
hint?: string;
|
|
8
8
|
logoUrl?: string;
|
|
9
9
|
error?: string;
|
|
10
|
-
otpEnabled?: boolean;
|
|
11
10
|
}>();
|
|
12
|
-
const emit = defineEmits<{
|
|
11
|
+
const emit = defineEmits<{
|
|
12
|
+
login: [username: string, password: string];
|
|
13
|
+
}>();
|
|
13
14
|
|
|
14
15
|
const username = ref("");
|
|
15
16
|
const password = ref("");
|
|
16
|
-
const otp = ref("");
|
|
17
17
|
const loading = ref(false);
|
|
18
18
|
|
|
19
19
|
async function submit() {
|
|
20
20
|
loading.value = true;
|
|
21
21
|
try {
|
|
22
|
-
emit("login", username.value, password.value
|
|
22
|
+
emit("login", username.value, password.value);
|
|
23
23
|
} finally {
|
|
24
24
|
loading.value = false;
|
|
25
25
|
}
|
|
@@ -34,7 +34,12 @@ async function submit() {
|
|
|
34
34
|
<h2 v-else class="ys-login__title">{{ appTitle }}</h2>
|
|
35
35
|
<el-form @submit.prevent="submit">
|
|
36
36
|
<el-form-item>
|
|
37
|
-
<el-input
|
|
37
|
+
<el-input
|
|
38
|
+
v-model="username"
|
|
39
|
+
placeholder="用户名"
|
|
40
|
+
size="large"
|
|
41
|
+
@keyup.enter="submit"
|
|
42
|
+
/>
|
|
38
43
|
</el-form-item>
|
|
39
44
|
<el-form-item>
|
|
40
45
|
<el-input
|
|
@@ -46,17 +51,13 @@ async function submit() {
|
|
|
46
51
|
@keyup.enter="submit"
|
|
47
52
|
/>
|
|
48
53
|
</el-form-item>
|
|
49
|
-
<el-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
@keyup.enter="submit"
|
|
57
|
-
/>
|
|
58
|
-
</el-form-item>
|
|
59
|
-
<el-alert v-if="error" :title="error" type="error" :closable="false" show-icon />
|
|
54
|
+
<el-alert
|
|
55
|
+
v-if="error"
|
|
56
|
+
:title="error"
|
|
57
|
+
type="error"
|
|
58
|
+
:closable="false"
|
|
59
|
+
show-icon
|
|
60
|
+
/>
|
|
60
61
|
<el-button
|
|
61
62
|
type="primary"
|
|
62
63
|
size="large"
|
package/src/index.ts
CHANGED
|
@@ -12,5 +12,7 @@ export { default as YsLoginPage } from "./components/YsLoginPage.vue";
|
|
|
12
12
|
export { default as YsSettingsCenterDialog } from "./components/YsSettingsCenterDialog.vue";
|
|
13
13
|
export { default as YsPortalGrid } from "./components/YsPortalGrid.vue";
|
|
14
14
|
export { default as YsRoleTag } from "./components/YsRoleTag.vue";
|
|
15
|
+
export { default as YsBoolMark } from "./components/YsBoolMark.vue";
|
|
16
|
+
export { default as YsSegmented } from "./components/YsSegmented.vue";
|
|
15
17
|
export { enumOptions, enumLabel, type EnumOption } from "./tokens-runtime";
|
|
16
18
|
export { registerColumnWidths, columnWidth, type ColumnWidthMap } from "./columnWidths";
|