befly-admin-ui 1.39.0 → 1.41.0

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.
@@ -1,24 +1,10 @@
1
1
  <template>
2
- <TDialog
3
- v-model:visible="$Data.innerVisible"
4
- :header="$Prop.title === '' ? true : $Prop.title"
5
- :width="$Prop.width"
6
- dialog-class-name="page-dialog"
7
- placement="center"
8
- attach="body"
9
- :close-btn="false"
10
- :footer="true"
11
- :confirm-loading="$Prop.confirmLoading"
12
- :close-on-overlay-click="false"
13
- :close-on-esc-keydown="false"
14
- @close="$Method.onDialogClose"
15
- @confirm="$Method.onDialogConfirm"
16
- @cancel="$Method.onDialogCancel"
17
- >
18
- <template #footer>
2
+ <TDialog v-model:visible="$Data.innerVisible" :header="$Prop.title" :width="$Prop.width" :dialog-class-name="dialogClassName" placement="center" attach="body" :footer="$Prop.isConfirm" :close-on-overlay-click="false" :close-on-esc-keydown="false" @close="$Method.onClose">
3
+ <template v-if="$Prop.isConfirm" #footer>
19
4
  <div class="dialog-footer">
20
- <TButton variant="outline" @click="$Method.onFooterClose">关闭</TButton>
21
- <TButton v-if="$Prop.isConfirm" theme="primary" :loading="$Prop.confirmLoading" @click="$Method.onFooterConfirm">确定</TButton>
5
+ <TPopconfirm content="确认提交吗?" @confirm="$Method.onConfirm">
6
+ <TButton theme="primary" :loading="$Prop.confirmLoading">确定</TButton>
7
+ </TPopconfirm>
22
8
  </div>
23
9
  </template>
24
10
  <div class="dialog-wrapper">
@@ -28,21 +14,21 @@
28
14
  </template>
29
15
 
30
16
  <script setup>
31
- import { onBeforeUnmount, onMounted, reactive, watch } from "vue";
17
+ import { Popconfirm as TPopconfirm } from "tdesign-vue-next";
18
+ import { computed, onBeforeUnmount, onMounted, reactive, watch } from "vue";
32
19
 
33
20
  defineOptions({
34
21
  inheritAttrs: false
35
22
  });
36
23
 
37
24
  const $Const = {
38
- openDelay: 100,
39
25
  closeDelay: 300
40
26
  };
41
27
 
42
28
  const $Prop = defineProps({
43
29
  modelValue: {
44
30
  type: Boolean,
45
- default: undefined
31
+ default: false
46
32
  },
47
33
  title: {
48
34
  type: String,
@@ -50,7 +36,7 @@ const $Prop = defineProps({
50
36
  },
51
37
  width: {
52
38
  type: String,
53
- default: "600px"
39
+ default: "800px"
54
40
  },
55
41
  dialogClassName: {
56
42
  type: String,
@@ -66,11 +52,10 @@ const $Prop = defineProps({
66
52
  }
67
53
  });
68
54
 
69
- const $Emit = defineEmits(["update:modelValue", "close", "confirm", "cancel"]);
55
+ const $Emit = defineEmits(["update:modelValue", "close", "confirm"]);
70
56
 
71
57
  const $From = {
72
- openDelayTimer: null,
73
- closeDelayTimer: null
58
+ closeTimer: null
74
59
  };
75
60
 
76
61
  const $Data = reactive({
@@ -78,25 +63,12 @@ const $Data = reactive({
78
63
  });
79
64
 
80
65
  const $Method = {
81
- clearTimer: function (timer) {
82
- if (timer) {
83
- clearTimeout(timer);
84
- }
85
- return null;
86
- },
87
66
  open: function () {
88
67
  $Emit("update:modelValue", true);
89
68
  },
90
69
  close: function () {
91
- $From.openDelayTimer = $Method.clearTimer($From.openDelayTimer);
92
- $From.closeDelayTimer = $Method.clearTimer($From.closeDelayTimer);
93
-
70
+ clearTimeout($From.closeTimer);
94
71
  $Data.innerVisible = false;
95
- // 延迟通知上层关闭:配合 v-if,保证离场动画播完再卸载
96
- $From.closeDelayTimer = setTimeout(() => {
97
- $Emit("update:modelValue", false);
98
- $From.closeDelayTimer = null;
99
- }, $Const.closeDelay);
100
72
  },
101
73
  toggle: function () {
102
74
  if ($Data.innerVisible) {
@@ -105,6 +77,9 @@ const $Method = {
105
77
  }
106
78
  $Method.open();
107
79
  },
80
+ getVisible: function () {
81
+ return $Data.innerVisible;
82
+ },
108
83
  createEventContext: function (trigger) {
109
84
  return {
110
85
  trigger: trigger,
@@ -112,83 +87,57 @@ const $Method = {
112
87
  open: $Method.open,
113
88
  close: $Method.close,
114
89
  toggle: $Method.toggle,
115
- getVisible: () => $Data.innerVisible
90
+ getVisible: $Method.getVisible
116
91
  };
117
92
  },
118
- applyModelValue: function (value) {
119
- if (value) {
120
- // 关键点:先渲染为 false,再延迟 true,保证 v-if + 初次 visible=true 时也能触发进入动画
121
- $From.openDelayTimer = $Method.clearTimer($From.openDelayTimer);
122
- $Data.innerVisible = false;
123
- $From.openDelayTimer = setTimeout(() => {
124
- $Data.innerVisible = true;
125
- $From.openDelayTimer = null;
126
- }, $Const.openDelay);
127
- return;
128
- }
129
-
130
- $From.openDelayTimer = $Method.clearTimer($From.openDelayTimer);
131
- $Data.innerVisible = false;
132
- },
133
- closeByTrigger: function (trigger) {
134
- // 固定交互:confirm 不自动关闭(等待异步提交成功后由调用侧 context.close() 决定关闭)
135
- if (trigger === "confirm") {
136
- return;
137
- }
138
- // cancel/close 自动关闭
93
+ onClose: function () {
94
+ $Emit("close", $Method.createEventContext("close"));
139
95
  $Method.close();
140
96
  },
141
- onDialogClose: function () {
142
- const context = $Method.createEventContext("close");
143
- $Method.closeByTrigger("close");
144
- $Emit("close", context);
145
- },
146
- onDialogConfirm: function () {
147
- const context = $Method.createEventContext("confirm");
148
- $Emit("confirm", context);
149
- $Method.closeByTrigger("confirm");
150
- },
151
- onDialogCancel: function () {
152
- const context = $Method.createEventContext("cancel");
153
- $Emit("cancel", context);
154
- $Method.closeByTrigger("cancel");
155
- },
156
- onFooterConfirm: function () {
157
- const context = $Method.createEventContext("confirm");
158
- $Emit("confirm", context);
159
- $Method.closeByTrigger("confirm");
160
- },
161
- onFooterClose: function () {
162
- const context = $Method.createEventContext("cancel");
163
- $Emit("cancel", context);
164
- $Method.closeByTrigger("cancel");
165
- },
166
- getVisible: function () {
167
- return $Data.innerVisible;
97
+ onConfirm: function () {
98
+ $Emit("confirm", $Method.createEventContext("confirm"));
99
+ // confirm 不自动关闭,由调用侧通过 context.close() 决定关闭时机
168
100
  }
169
101
  };
170
102
 
103
+ const dialogClassName = computed(() => ["page-dialog", $Prop.dialogClassName].filter(Boolean).join(" "));
104
+
171
105
  onMounted(() => {
172
106
  if ($Prop.modelValue === true) {
173
- $Method.applyModelValue(true);
107
+ $Data.innerVisible = true;
174
108
  }
175
109
  });
176
110
 
177
111
  onBeforeUnmount(() => {
178
- $From.openDelayTimer = $Method.clearTimer($From.openDelayTimer);
179
- $From.closeDelayTimer = $Method.clearTimer($From.closeDelayTimer);
112
+ clearTimeout($From.closeTimer);
180
113
  });
181
114
 
182
115
  watch(
183
116
  () => $Prop.modelValue,
184
117
  (value) => {
185
- if (value !== true && value !== false) {
118
+ if (value === true) {
119
+ $Data.innerVisible = true;
120
+ } else if (value === false) {
121
+ $Data.innerVisible = false;
122
+ }
123
+ }
124
+ );
125
+
126
+ watch(
127
+ () => $Data.innerVisible,
128
+ (value) => {
129
+ if (value === true) {
130
+ clearTimeout($From.closeTimer);
186
131
  return;
187
132
  }
188
133
 
189
- $Method.applyModelValue(value);
190
- },
191
- { immediate: false }
134
+ if ($Prop.modelValue === true) {
135
+ $From.closeTimer = setTimeout(() => {
136
+ $Emit("update:modelValue", false);
137
+ $From.closeTimer = null;
138
+ }, $Const.closeDelay);
139
+ }
140
+ }
192
141
  );
193
142
 
194
143
  defineExpose({
@@ -81,8 +81,7 @@
81
81
  }
82
82
  "
83
83
  :model="$Data.passwordForm"
84
- label-width="100px"
85
- label-position="left"
84
+ label-align="top"
86
85
  :rules="$Const.passwordFormRules"
87
86
  >
88
87
  <TFormItem label="新密码" prop="password">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "befly-admin-ui",
3
- "version": "1.39.0",
3
+ "version": "1.41.0",
4
4
  "gitHead": "071d17be177355cdd61f30659c6e4c5873f87d39",
5
5
  "private": false,
6
6
  "description": "Befly - 管理后台功能组件",
@@ -34,6 +34,7 @@
34
34
  ".": "./package.json",
35
35
  "./components/*": "./components/*",
36
36
  "./layouts/*": "./layouts/*",
37
+ "./views/*": "./views/*",
37
38
  "./styles/*": "./styles/*",
38
39
  "./utils/*": "./utils/*.js"
39
40
  },
@@ -1,39 +1,51 @@
1
- <template>
1
+ <template>
2
2
  <PageDialog v-model="$Computed.visible" :title="$Computed.dialogTitle" @confirm="$Method.handleSubmit">
3
3
  <TForm
4
4
  :data="$Data.formData"
5
5
  :rules="$Const.formRules"
6
- label-width="100px"
6
+ label-align="top"
7
7
  :ref="
8
8
  (value) => {
9
9
  $From.formRef = value;
10
10
  }
11
11
  "
12
12
  >
13
- <TFormItem label="字典类型" name="typeCode">
14
- <TSelect v-model="$Data.formData.typeCode" placeholder="请选择字典类型" filterable>
15
- <TOption v-for="item in typeList" :key="item.code" :value="item.code" :label="item.name" />
16
- </TSelect>
17
- </TFormItem>
18
- <TFormItem label="键值" name="key">
19
- <TInput v-model="$Data.formData.key" placeholder="请输入键名(英文/数字/下划线)" />
20
- </TFormItem>
21
- <TFormItem label="标签" name="label">
22
- <TInput v-model="$Data.formData.label" placeholder="请输入标签(显示名称)" />
23
- </TFormItem>
24
- <TFormItem label="排序" name="sort">
25
- <TInputNumber v-model="$Data.formData.sort" :min="0" placeholder="请输入排序值" />
26
- </TFormItem>
27
- <TFormItem label="备注" name="remark">
28
- <TTextarea v-model="$Data.formData.remark" placeholder="请输入备注信息" :autosize="{ minRows: 3, maxRows: 6 }" />
29
- </TFormItem>
13
+ <t-row :gutter="[16, 16]">
14
+ <t-col :span="6">
15
+ <TFormItem label="字典类型" name="typeCode">
16
+ <TSelect v-model="$Data.formData.typeCode" placeholder="请选择字典类型" filterable>
17
+ <TOption v-for="item in typeList" :key="item.code" :value="item.code" :label="item.name" />
18
+ </TSelect>
19
+ </TFormItem>
20
+ </t-col>
21
+ <t-col :span="6">
22
+ <TFormItem label="键值" name="key">
23
+ <TInput v-model="$Data.formData.key" placeholder="请输入键名(英文/数字/下划线)" />
24
+ </TFormItem>
25
+ </t-col>
26
+ <t-col :span="6">
27
+ <TFormItem label="标签" name="label">
28
+ <TInput v-model="$Data.formData.label" placeholder="请输入标签(显示名称)" />
29
+ </TFormItem>
30
+ </t-col>
31
+ <t-col :span="6">
32
+ <TFormItem label="排序" name="sort">
33
+ <TInputNumber v-model="$Data.formData.sort" :min="0" placeholder="请输入排序值" />
34
+ </TFormItem>
35
+ </t-col>
36
+ <t-col :span="12">
37
+ <TFormItem label="备注" name="remark">
38
+ <TTextarea v-model="$Data.formData.remark" placeholder="请输入备注信息" :autosize="{ minRows: 3, maxRows: 6 }" />
39
+ </TFormItem>
40
+ </t-col>
41
+ </t-row>
30
42
  </TForm>
31
43
  </PageDialog>
32
44
  </template>
33
45
 
34
46
  <script setup>
35
47
  import PageDialog from "befly-admin-ui/components/pageDialog.vue";
36
- import { MessagePlugin } from "tdesign-vue-next";
48
+ import { Col as TCol, MessagePlugin, Row as TRow } from "tdesign-vue-next";
37
49
  import { computed, reactive } from "vue";
38
50
 
39
51
  import { $Http } from "@/plugins/http.js";
@@ -3,32 +3,42 @@
3
3
  <TForm
4
4
  :data="$Data.formData"
5
5
  :rules="$Const.formRules"
6
- label-width="100px"
6
+ label-align="top"
7
7
  :ref="
8
8
  (value) => {
9
9
  $From.formRef = value;
10
10
  }
11
11
  "
12
12
  >
13
- <TFormItem label="类型代码" name="code">
14
- <TInput v-model="$Data.formData.code" placeholder="请输入类型代码(英文/数字/下划线)" :disabled="actionType === 'upd'" />
15
- </TFormItem>
16
- <TFormItem label="类型名称" name="name">
17
- <TInput v-model="$Data.formData.name" placeholder="请输入类型名称" />
18
- </TFormItem>
19
- <TFormItem label="描述" name="description">
20
- <TTextarea v-model="$Data.formData.description" placeholder="请输入描述信息" :autosize="{ minRows: 3, maxRows: 6 }" />
21
- </TFormItem>
22
- <TFormItem label="排序" name="sort">
23
- <TInputNumber v-model="$Data.formData.sort" :min="0" placeholder="请输入排序值" />
24
- </TFormItem>
13
+ <t-row :gutter="[16, 16]">
14
+ <t-col :span="6">
15
+ <TFormItem label="类型代码" name="code">
16
+ <TInput v-model="$Data.formData.code" placeholder="请输入类型代码(英文/数字/下划线)" :disabled="actionType === 'upd'" />
17
+ </TFormItem>
18
+ </t-col>
19
+ <t-col :span="6">
20
+ <TFormItem label="类型名称" name="name">
21
+ <TInput v-model="$Data.formData.name" placeholder="请输入类型名称" />
22
+ </TFormItem>
23
+ </t-col>
24
+ <t-col :span="8">
25
+ <TFormItem label="描述" name="description">
26
+ <TInput v-model="$Data.formData.description" placeholder="请输入描述信息" />
27
+ </TFormItem>
28
+ </t-col>
29
+ <t-col :span="4">
30
+ <TFormItem label="排序" name="sort">
31
+ <TInputNumber v-model="$Data.formData.sort" :min="0" placeholder="请输入排序值" />
32
+ </TFormItem>
33
+ </t-col>
34
+ </t-row>
25
35
  </TForm>
26
36
  </PageDialog>
27
37
  </template>
28
38
 
29
39
  <script setup>
30
40
  import PageDialog from "befly-admin-ui/components/pageDialog.vue";
31
- import { MessagePlugin } from "tdesign-vue-next";
41
+ import { Col as TCol, MessagePlugin, Row as TRow } from "tdesign-vue-next";
32
42
  import { computed, reactive } from "vue";
33
43
 
34
44
  import { $Http } from "@/plugins/http.js";
@@ -0,0 +1,57 @@
1
+ <template>
2
+ <div class="page-not-found">
3
+ <div class="page-not-found__content">
4
+ <div class="page-not-found__icon">
5
+ <t-icon name="error-circle" size="64px" />
6
+ </div>
7
+ <h1 class="page-not-found__title">页面不见了</h1>
8
+ <p class="page-not-found__desc">你访问的页面可能已经删除、移动或从未存在过</p>
9
+ <t-button theme="primary" @click="$Method.goHome">返回首页</t-button>
10
+ </div>
11
+ </div>
12
+ </template>
13
+
14
+ <script setup>
15
+ import { Button as TButton, Icon as TIcon } from "tdesign-vue-next";
16
+ import { useRouter } from "vue-router";
17
+
18
+ const $Router = useRouter();
19
+
20
+ const $Method = {
21
+ goHome: function () {
22
+ $Router.push("/");
23
+ }
24
+ };
25
+ </script>
26
+
27
+ <style scoped lang="scss">
28
+ .page-not-found {
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ height: 100vh;
33
+
34
+ &__content {
35
+ display: flex;
36
+ flex-direction: column;
37
+ align-items: center;
38
+ gap: 16px;
39
+ text-align: center;
40
+ }
41
+
42
+ &__icon {
43
+ color: var(--color-text-secondary, #4e5969);
44
+ }
45
+
46
+ &__title {
47
+ margin: 0;
48
+ font-size: var(--font-size-title, 18px);
49
+ color: var(--color-text-primary, #1f2329);
50
+ }
51
+
52
+ &__desc {
53
+ margin: 0;
54
+ color: var(--color-text-secondary, #4e5969);
55
+ }
56
+ }
57
+ </style>
@@ -1,24 +1,40 @@
1
- <template>
1
+ <template>
2
2
  <PageDialog v-model="$Computed.dialogVisible" :title="$Computed.dialogTitle" :confirm-loading="$Data.submitting" @confirm="$Method.onSubmit">
3
3
  <div class="dialog-wrapper">
4
- <TForm :model="$Data.formData" label-width="80px" label-position="left" label-align="left" :rules="$Const.formRules" :ref="(el) => ($From.formRef = el)">
5
- <TFormItem label="角色" prop="roleCode">
6
- <TSelect v-model="$Data.formData.roleCode" :options="$Type.roleOptions" placeholder="请选择角色" />
7
- </TFormItem>
8
- <TFormItem label="用户名" prop="username">
9
- <TInput v-model="$Data.formData.username" placeholder="请输入用户名" :disabled="$Computed.isUpdate" />
10
- </TFormItem>
11
- <TFormItem v-if="$Computed.isAdd" label="密码" prop="password">
12
- <TInput v-model="$Data.formData.password" type="password" placeholder="请输入密码,至少6位" />
13
- </TFormItem>
14
- <TFormItem label="昵称" prop="nickname">
15
- <TInput v-model="$Data.formData.nickname" placeholder="请输入昵称" />
16
- </TFormItem>
17
- <TFormItem v-if="$Computed.isUpdate" label="状态" prop="state">
18
- <TRadioGroup v-model="$Data.formData.state">
19
- <TRadio v-for="item in $Type.stateOptions" :key="item.value" :value="item.value">{{ item.label }}</TRadio>
20
- </TRadioGroup>
21
- </TFormItem>
4
+ <TForm :model="$Data.formData" label-align="top" width="600px" :rules="$Const.formRules" :ref="(el) => ($From.formRef = el)">
5
+ <t-row :gutter="[16, 16]">
6
+ <t-col :span="6">
7
+ <TFormItem label="角色" prop="roleCode">
8
+ <TSelect v-model="$Data.formData.roleCode" :options="$Type.roleOptions" placeholder="请选择角色" />
9
+ </TFormItem>
10
+ </t-col>
11
+ <t-col :span="6">
12
+ <TFormItem label="用户名" prop="username">
13
+ <TInput v-model="$Data.formData.username" placeholder="请输入用户名" :disabled="$Computed.isUpdate" />
14
+ </TFormItem>
15
+ </t-col>
16
+ </t-row>
17
+ <t-row :gutter="[16, 16]">
18
+ <t-col v-if="$Computed.isAdd" :span="6">
19
+ <TFormItem label="密码" prop="password">
20
+ <TInput v-model="$Data.formData.password" type="password" placeholder="请输入密码,至少6位" />
21
+ </TFormItem>
22
+ </t-col>
23
+ <t-col :span="6">
24
+ <TFormItem label="昵称" prop="nickname">
25
+ <TInput v-model="$Data.formData.nickname" placeholder="请输入昵称" />
26
+ </TFormItem>
27
+ </t-col>
28
+ </t-row>
29
+ <t-row v-if="$Computed.isUpdate" :gutter="[16, 16]">
30
+ <t-col :span="12">
31
+ <TFormItem label="状态" prop="state">
32
+ <TRadioGroup v-model="$Data.formData.state">
33
+ <TRadio v-for="item in $Type.stateOptions" :key="item.value" :value="item.value">{{ item.label }}</TRadio>
34
+ </TRadioGroup>
35
+ </TFormItem>
36
+ </t-col>
37
+ </t-row>
22
38
  </TForm>
23
39
  </div>
24
40
  </PageDialog>
@@ -28,10 +44,7 @@
28
44
  import PageDialog from "befly-admin-ui/components/pageDialog.vue";
29
45
  import { fieldClear } from "befly-admin-ui/utils/fieldClear";
30
46
  import { hashPassword } from "befly-admin-ui/utils/hashPassword";
31
- import {
32
- //
33
- MessagePlugin
34
- } from "tdesign-vue-next";
47
+ import { Col as TCol, MessagePlugin, Row as TRow } from "tdesign-vue-next";
35
48
  import { computed, reactive } from "vue";
36
49
 
37
50
  import { $Http } from "@/plugins/http.js";
@@ -1,10 +1,9 @@
1
- <template>
1
+ <template>
2
2
  <PageDialog v-model="$Computed.dialogVisible" :title="$Computed.dialogTitle" :confirm-loading="$Data.submitting" @confirm="$Method.onSubmit">
3
3
  <div class="comp-role-edit">
4
4
  <TForm
5
5
  :model="$Data.formData"
6
- label-width="120px"
7
- label-position="left"
6
+ label-align="top"
8
7
  :rules="$Const.formRules"
9
8
  :ref="
10
9
  (value) => {
@@ -12,24 +11,36 @@
12
11
  }
13
12
  "
14
13
  >
15
- <TFormItem label="角色名称" prop="name">
16
- <TInput v-model="$Data.formData.name" placeholder="请输入角色名称" />
17
- </TFormItem>
18
- <TFormItem label="角色代码" prop="code">
19
- <TInput v-model="$Data.formData.code" placeholder="请输入角色代码,如:admin" />
20
- </TFormItem>
21
- <TFormItem label="角色描述" prop="description">
22
- <TInput v-model="$Data.formData.description" placeholder="请输入角色描述" />
23
- </TFormItem>
24
- <TFormItem label="排序" prop="sort">
25
- <TInputNumber v-model="$Data.formData.sort" :min="0" :max="9999" />
26
- </TFormItem>
27
- <TFormItem label="状态" prop="state">
28
- <TRadioGroup v-model="$Data.formData.state">
29
- <TRadio :value="1">正常</TRadio>
30
- <TRadio :value="2">禁用</TRadio>
31
- </TRadioGroup>
32
- </TFormItem>
14
+ <t-row :gutter="[16, 16]">
15
+ <t-col :span="6">
16
+ <TFormItem label="角色名称" prop="name">
17
+ <TInput v-model="$Data.formData.name" placeholder="请输入角色名称" />
18
+ </TFormItem>
19
+ </t-col>
20
+ <t-col :span="6">
21
+ <TFormItem label="角色代码" prop="code">
22
+ <TInput v-model="$Data.formData.code" placeholder="请输入角色代码,如:admin" />
23
+ </TFormItem>
24
+ </t-col>
25
+ <t-col :span="6">
26
+ <TFormItem label="角色描述" prop="description">
27
+ <TInput v-model="$Data.formData.description" placeholder="请输入角色描述" />
28
+ </TFormItem>
29
+ </t-col>
30
+ <t-col :span="3">
31
+ <TFormItem label="排序" prop="sort">
32
+ <TInputNumber v-model="$Data.formData.sort" :min="0" :max="9999" />
33
+ </TFormItem>
34
+ </t-col>
35
+ <t-col :span="3">
36
+ <TFormItem label="状态" prop="state">
37
+ <TRadioGroup v-model="$Data.formData.state">
38
+ <TRadio :value="1">正常</TRadio>
39
+ <TRadio :value="2">禁用</TRadio>
40
+ </TRadioGroup>
41
+ </TFormItem>
42
+ </t-col>
43
+ </t-row>
33
44
  </TForm>
34
45
  </div>
35
46
  </PageDialog>
@@ -38,10 +49,7 @@
38
49
  <script setup>
39
50
  import PageDialog from "befly-admin-ui/components/pageDialog.vue";
40
51
  import { fieldClear } from "befly-admin-ui/utils/fieldClear";
41
- import {
42
- //
43
- MessagePlugin
44
- } from "tdesign-vue-next";
52
+ import { Col as TCol, MessagePlugin, Row as TRow } from "tdesign-vue-next";
45
53
  import { computed, reactive, ref } from "vue";
46
54
 
47
55
  import { $Http } from "@/plugins/http.js";
@@ -1,180 +0,0 @@
1
- <template>
2
- <PageDialog v-model="$Computed.dialogVisible" :title="$Computed.dialogTitle" :confirm-loading="$Data.submitting" @confirm="$Method.onSubmit">
3
- <TForm
4
- :model="$Data.formData"
5
- label-width="120px"
6
- label-position="left"
7
- :rules="$Const.formRules"
8
- :ref="
9
- (value) => {
10
- $From.formRef = value;
11
- }
12
- "
13
- >
14
- <TFormItem label="配置名称" prop="name">
15
- <TInput v-model="$Data.formData.name" placeholder="请输入配置名称" :disabled="$Data.isSystem" />
16
- </TFormItem>
17
- <TFormItem label="配置代码" prop="code">
18
- <TInput v-model="$Data.formData.code" placeholder="请输入配置代码,如:site_name" :disabled="$Prop.actionType === 'upd'" />
19
- </TFormItem>
20
- <TFormItem label="配置值" prop="value">
21
- <TTextarea v-if="$Data.formData.valueType === 'json' || $Data.formData.valueType === 'text'" v-model="$Data.formData.value" placeholder="请输入配置值" :autosize="{ minRows: 3, maxRows: 8 }" />
22
- <TInput v-else v-model="$Data.formData.value" placeholder="请输入配置值" />
23
- </TFormItem>
24
- <TFormItem label="值类型" prop="valueType">
25
- <TSelect v-model="$Data.formData.valueType" :disabled="$Data.isSystem">
26
- <TOption label="字符串" value="string" />
27
- <TOption label="数字" value="number" />
28
- <TOption label="布尔" value="boolean" />
29
- <TOption label="JSON" value="json" />
30
- </TSelect>
31
- </TFormItem>
32
- <TFormItem label="配置分组" prop="group">
33
- <TSelect v-model="$Data.formData.group" placeholder="请选择分组" clearable :disabled="$Data.isSystem">
34
- <TOption v-for="item in $Const.groupOptions" :key="item" :label="item" :value="item" />
35
- </TSelect>
36
- </TFormItem>
37
- <TFormItem label="排序" prop="sort">
38
- <TInputNumber v-model="$Data.formData.sort" :min="0" :max="9999" :disabled="$Data.isSystem" />
39
- </TFormItem>
40
- <TFormItem label="描述说明" prop="description">
41
- <TTextarea v-model="$Data.formData.description" placeholder="请输入描述说明" :autosize="{ minRows: 2, maxRows: 4 }" :disabled="$Data.isSystem" />
42
- </TFormItem>
43
- <TFormItem v-if="$Prop.actionType === 'upd' && !$Data.isSystem" label="状态" prop="state">
44
- <TRadioGroup v-model="$Data.formData.state">
45
- <TRadio :value="1">正常</TRadio>
46
- <TRadio :value="2">禁用</TRadio>
47
- </TRadioGroup>
48
- </TFormItem>
49
- </TForm>
50
- </PageDialog>
51
- </template>
52
-
53
- <script setup>
54
- import PageDialog from "befly-admin-ui/components/pageDialog.vue";
55
- import { MessagePlugin } from "tdesign-vue-next";
56
- import { computed, reactive } from "vue";
57
-
58
- import { $Http } from "@/plugins/http.js";
59
-
60
- const $Prop = defineProps({
61
- modelValue: {
62
- type: Boolean,
63
- default: false
64
- },
65
- actionType: {
66
- type: String,
67
- default: "add"
68
- },
69
- rowData: {
70
- type: Object,
71
- default: () => ({})
72
- }
73
- });
74
-
75
- const $Emit = defineEmits(["update:modelValue", "success"]);
76
-
77
- const $Const = {
78
- createDefaultFormData: function () {
79
- return {
80
- id: 0,
81
- name: "",
82
- code: "",
83
- value: "",
84
- valueType: "string",
85
- group: "",
86
- sort: 0,
87
- description: "",
88
- state: 1
89
- };
90
- },
91
- formRules: {
92
- name: [{ required: true, message: "请输入配置名称", trigger: "blur" }],
93
- code: [
94
- { required: true, message: "请输入配置代码", trigger: "blur" },
95
- { pattern: /^[a-zA-Z0-9_]+$/, message: "配置代码只能包含字母、数字和下划线", trigger: "blur" }
96
- ],
97
- value: [{ required: true, message: "请输入配置值", trigger: "blur" }],
98
- valueType: [{ required: true, message: "请选择值类型", trigger: "change" }]
99
- },
100
- groupOptions: ["基础配置", "邮件配置", "存储配置", "安全配置", "其他"]
101
- };
102
-
103
- const $From = {
104
- formRef: null
105
- };
106
-
107
- const $Data = reactive({
108
- submitting: false,
109
- isSystem: false,
110
- formData: $Const.createDefaultFormData()
111
- });
112
-
113
- const $Computed = reactive({
114
- dialogVisible: computed({
115
- get: () => $Prop.modelValue,
116
- set: (value) => {
117
- $Emit("update:modelValue", value);
118
- }
119
- }),
120
- dialogTitle: computed(() => ($Prop.actionType === "upd" ? "编辑配置" : "添加配置"))
121
- });
122
-
123
- const $Method = {
124
- resetFormData: function () {
125
- Object.assign($Data.formData, $Const.createDefaultFormData());
126
- $Data.isSystem = false;
127
- },
128
- initData: function () {
129
- $Method.onShow();
130
- },
131
- onShow: function () {
132
- if ($Prop.actionType === "upd" && $Prop.rowData) {
133
- const row = $Prop.rowData;
134
- $Data.formData.id = row["id"] || 0;
135
- $Data.formData.name = row["name"] || "";
136
- $Data.formData.code = row["code"] || "";
137
- $Data.formData.value = row["value"] || "";
138
- $Data.formData.valueType = row["valueType"] || "string";
139
- $Data.formData.group = row["group"] || "";
140
- $Data.formData.sort = row["sort"] || 0;
141
- $Data.formData.description = row["description"] || "";
142
- $Data.formData.state = row["state"] || 1;
143
- $Data.isSystem = row["isSystem"] === 1;
144
- return;
145
- }
146
-
147
- $Method.resetFormData();
148
- },
149
- onSubmit: async function (context) {
150
- const form = $From.formRef;
151
- if (!form) {
152
- MessagePlugin.warning("表单未就绪");
153
- return;
154
- }
155
-
156
- const valid = await form.validate();
157
- if (valid !== true) return;
158
-
159
- $Data.submitting = true;
160
- try {
161
- const api = $Prop.actionType === "upd" ? "/core/sysConfig/update" : "/core/sysConfig/insert";
162
- await $Http(api, $Data.formData);
163
-
164
- MessagePlugin.success($Prop.actionType === "upd" ? "编辑成功" : "添加成功");
165
- $Emit("success");
166
- if (context && typeof context.close === "function") {
167
- context.close();
168
- }
169
- } catch (error) {
170
- MessagePlugin.error(error.msg || error.message || "操作失败");
171
- } finally {
172
- $Data.submitting = false;
173
- }
174
- }
175
- };
176
-
177
- $Method.initData();
178
- </script>
179
-
180
- <style scoped lang="scss"></style>
@@ -1,173 +0,0 @@
1
- <template>
2
- <PageTableDetail class="page-sys-config page-table" :columns="$Data.columns" :endpoints="$Data.endpoints" :table-slot-names="['isSystem', 'valueType', 'state']">
3
- <template #toolLeft="scope">
4
- <TButton theme="primary" @click="$Method.onAdd">
5
- <template #icon>
6
- <AddIcon />
7
- </template>
8
- 新增配置
9
- </TButton>
10
- <TSelect v-model="$Data.filter.group" placeholder="配置分组" clearable style="width: 150px" @change="$Method.handleFilter(scope.reload)">
11
- <TOption v-for="item in $Data.groupOptions" :key="item" :label="item" :value="item" />
12
- </TSelect>
13
- </template>
14
-
15
- <template #isSystem="{ row }">
16
- <TTag v-if="row.isSystem === 1" shape="round" theme="warning" variant="light-outline">系统</TTag>
17
- <TTag v-else shape="round" variant="light-outline">自定义</TTag>
18
- </template>
19
-
20
- <template #valueType="{ row }">
21
- <TTag shape="round" variant="light-outline">{{ row.valueType }}</TTag>
22
- </template>
23
-
24
- <template #state="{ row }">
25
- <TTag v-if="row.state === 1" shape="round" theme="success" variant="light-outline">正常</TTag>
26
- <TTag v-else-if="row.state === 2" shape="round" theme="warning" variant="light-outline">禁用</TTag>
27
- </template>
28
-
29
- <template #operation="{ row, deleteRow }">
30
- <TDropdown trigger="click" placement="bottom-right" @click="$Method.onDropdownAction($event, row, deleteRow)">
31
- <TButton theme="primary" size="small">
32
- 操作
33
- <template #suffix><ChevronDownIcon /></template>
34
- </TButton>
35
- <TDropdownMenu slot="dropdown">
36
- <TDropdownItem value="upd">
37
- <EditIcon />
38
- 编辑
39
- </TDropdownItem>
40
- <TDropdownItem v-if="row.isSystem !== 1" value="del" :divider="true">
41
- <DeleteIcon style="width: 14px; height: 14px; margin-right: 6px" />
42
- 删除
43
- </TDropdownItem>
44
- </TDropdownMenu>
45
- </TDropdown>
46
- </template>
47
-
48
- <template #detail="scope">
49
- <DetailPanel :data="scope.row" :fields="$Data.columns">
50
- <template #isSystem="slotScope">
51
- <TTag v-if="slotScope.value === 1" shape="round" theme="warning" variant="light-outline">系统配置</TTag>
52
- <TTag v-else shape="round" variant="light-outline">自定义配置</TTag>
53
- </template>
54
- <template #valueType="slotScope">
55
- <TTag shape="round" variant="light-outline">{{ slotScope.value }}</TTag>
56
- </template>
57
- <template #value="slotScope">
58
- <pre class="config-value">{{ slotScope.value }}</pre>
59
- </template>
60
- </DetailPanel>
61
- </template>
62
-
63
- <template #dialogs="scope">
64
- <EditDialog v-if="$Data.editVisible" v-model="$Data.editVisible" :action-type="$Data.actionType" :row-data="$Data.rowData" @success="$Method.onDialogSuccess(scope.reload)" />
65
- </template>
66
- </PageTableDetail>
67
- </template>
68
-
69
- <script setup>
70
- import DetailPanel from "befly-admin-ui/components/detailPanel.vue";
71
- import PageTableDetail from "befly-admin-ui/components/pageTableDetail.vue";
72
- import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
73
- import { reactive } from "vue";
74
-
75
- import EditDialog from "./components/edit.vue";
76
-
77
- // 响应式数据
78
- const $Data = reactive({
79
- columns: withDefaultColumns([
80
- { colKey: "name", title: "配置名称", fixed: "left", width: 150 },
81
- { colKey: "code", title: "配置代码", ellipsis: true },
82
- { colKey: "value", title: "配置值", ellipsis: true, width: 200 },
83
- { colKey: "valueType", title: "值类型", width: 100 },
84
- { colKey: "group", title: "分组", width: 100 },
85
- { colKey: "sort", title: "排序", width: 80 },
86
- { colKey: "isSystem", title: "类型", width: 80 },
87
- { colKey: "state", title: "状态", width: 80 },
88
- { colKey: "operation", title: "操作", width: 100 },
89
- { colKey: "description", title: "描述说明", detail: true }
90
- ]),
91
- endpoints: {
92
- list: {
93
- path: "/core/sysConfig/select",
94
- dropValues: [0],
95
- dropKeyValue: {
96
- group: [""]
97
- },
98
- buildData: () => {
99
- return {
100
- group: $Data.filter.group
101
- };
102
- }
103
- },
104
- delete: {
105
- path: "/core/sysConfig/delete",
106
- idKey: "id",
107
- confirm: (row) => {
108
- return {
109
- header: "确认删除",
110
- body: `确认删除配置“${row.name}”吗?`,
111
- confirmBtn: "删除",
112
- status: "warning"
113
- };
114
- }
115
- }
116
- },
117
- editVisible: false,
118
- actionType: "add",
119
- rowData: {},
120
- filter: {
121
- group: ""
122
- },
123
- groupOptions: ["基础配置", "邮件配置", "存储配置", "安全配置", "其他"]
124
- });
125
-
126
- const $Method = {
127
- onAdd: function () {
128
- $Method.onAction("add", {});
129
- },
130
- handleFilter: function (reload) {
131
- reload({ keepSelection: false, resetPage: true });
132
- },
133
- onDialogSuccess: function (reload) {
134
- reload({ keepSelection: true });
135
- },
136
- onAction: function (command, rowData) {
137
- $Data.actionType = command;
138
- if (command === "add") {
139
- $Data.rowData = {};
140
- } else {
141
- $Data.rowData = Object.assign({}, rowData);
142
- }
143
-
144
- if (command === "add" || command === "upd") {
145
- $Data.editVisible = true;
146
- }
147
- },
148
- onDropdownAction: function (data, rowData, deleteRow) {
149
- const record = data;
150
- const rawValue = record && record["value"] ? record["value"] : "";
151
- const cmd = rawValue ? String(rawValue) : "";
152
- if (cmd === "del") {
153
- deleteRow(rowData);
154
- return;
155
- }
156
- $Method.onAction(cmd, rowData);
157
- }
158
- };
159
- </script>
160
-
161
- <style scoped lang="scss">
162
- .config-value {
163
- margin: 0;
164
- padding: 8px;
165
- background: var(--td-bg-color-container);
166
- border-radius: 4px;
167
- font-size: 12px;
168
- max-height: 150px;
169
- overflow: auto;
170
- white-space: pre-wrap;
171
- word-break: break-all;
172
- }
173
- </style>