@truenewx/tnxvue3 3.4.4 → 3.4.6

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.
Files changed (35) hide show
  1. package/package.json +18 -17
  2. package/src/bootstrap-vue/dialog/Dialog.vue +22 -10
  3. package/src/bootstrap-vue/select/Select.vue +3 -4
  4. package/src/components/ScrollView.vue +69 -0
  5. package/src/css.d.ts +4 -0
  6. package/src/element-plus/aj-captcha/utils/ase.js +4 -4
  7. package/src/element-plus/dialog/Dialog.vue +19 -7
  8. package/src/element-plus/drawer/Drawer.vue +20 -3
  9. package/src/element-plus/fss-upload/FssUpload.vue +1 -1
  10. package/src/element-plus/icon/Icon.vue +3 -0
  11. package/src/element-plus/select/Select.vue +3 -4
  12. package/src/element-plus/tnxel.css +0 -8
  13. package/src/element-plus/tnxel.ts +58 -72
  14. package/src/tdesign/mobile/calendar/Calendar.vue +121 -0
  15. package/src/tdesign/mobile/date-time-picker/DateTimePicker.vue +147 -0
  16. package/src/tdesign/mobile/dialog/Dialog.vue +179 -0
  17. package/src/tdesign/mobile/dialog/DialogContent.vue +13 -0
  18. package/src/tdesign/mobile/drawer/Drawer.vue +197 -0
  19. package/src/tdesign/mobile/drawer/DrawerContent.vue +13 -0
  20. package/src/tdesign/mobile/enum-select/EnumSelect.vue +164 -0
  21. package/src/tdesign/mobile/popup/Popup.vue +106 -0
  22. package/src/tdesign/mobile/region-picker/RegionPicker.vue +223 -0
  23. package/src/tdesign/mobile/select/Select.vue +479 -0
  24. package/src/tdesign/mobile/slide-radio-group/SlideRadioGroup.vue +397 -0
  25. package/src/tdesign/mobile/tnxtdm.css +125 -0
  26. package/src/tdesign/mobile/tnxtdm.ts +305 -1
  27. package/src/tdesign/tnxtd-validator.ts +14 -13
  28. package/src/tdesign/tnxtd.css +98 -0
  29. package/src/tdesign/tnxtd.ts +4 -0
  30. package/src/tnxvue-router.ts +59 -5
  31. package/src/tnxvue.ts +32 -11
  32. package/src/vue.d.ts +6 -0
  33. package/tsconfig.json +4 -7
  34. /package/src/{percent → components}/Percent.vue +0 -0
  35. /package/src/{text → components}/Text.vue +0 -0
@@ -0,0 +1,121 @@
1
+ <template>
2
+ <div class="tnxtdm-calendar">
3
+ <div class="tnxtdm-calendar__value">{{ modelValue }}</div>
4
+ <div class="tnxtdm-calendar__icon" :style="{color: iconColor}" @click="visible = true">
5
+ <t-icon name="calendar-1"/>
6
+ </div>
7
+ <t-calendar
8
+ v-model:visible="visible"
9
+ :value="calendarValue"
10
+ type="single"
11
+ switch-mode="year-month"
12
+ :min-date="finalMinDate"
13
+ :max-date="finalMaxDate"
14
+ :title="title"
15
+ @confirm="confirm"
16
+ />
17
+ </div>
18
+ </template>
19
+
20
+ <script>
21
+ const pattern = 'yyyy-MM-dd';
22
+
23
+ function parseDate(val) {
24
+ if (!val) {
25
+ return undefined;
26
+ }
27
+ if (val instanceof Date) {
28
+ return val;
29
+ }
30
+ if (typeof val === 'number') {
31
+ return new Date(val);
32
+ }
33
+ if (typeof val === 'string') {
34
+ val = val.replace(/-/g, '/');
35
+ }
36
+ const d = new Date(val);
37
+ if (!isNaN(d.getTime())) {
38
+ return d;
39
+ }
40
+ return undefined;
41
+ }
42
+
43
+ export default {
44
+ name: 'TnxtdmCalendar',
45
+ props: {
46
+ modelValue: String,
47
+ title: String,
48
+ defaultValue: {
49
+ type: String,
50
+ default: () => {
51
+ return new Date().format(pattern);
52
+ },
53
+ },
54
+ minDate: {
55
+ type: [String, Number, Date],
56
+ default: '1900-01-01',
57
+ },
58
+ maxDate: {
59
+ type: [String, Number, Date],
60
+ default: '2099-12-31',
61
+ },
62
+ iconColor: String,
63
+ },
64
+ data() {
65
+ return {
66
+ visible: false,
67
+ calendarValue: parseDate(this.modelValue || this.defaultValue),
68
+ };
69
+ },
70
+ computed: {
71
+ finalMinDate() {
72
+ return parseDate(this.minDate);
73
+ },
74
+ finalMaxDate() {
75
+ return parseDate(this.maxDate);
76
+ },
77
+ },
78
+ emits: ['update:modelValue'],
79
+ watch: {
80
+ modelValue() {
81
+ this.init();
82
+ },
83
+ visible(val) {
84
+ if (val) {
85
+ this.init();
86
+ }
87
+ },
88
+ },
89
+ mounted() {
90
+ this.init();
91
+ },
92
+ methods: {
93
+ init() {
94
+ let value = this.modelValue || this.defaultValue;
95
+ this.calendarValue = parseDate(value);
96
+ },
97
+ confirm(val) {
98
+ let result = new Date(val).format(pattern);
99
+ this.$emit('update:modelValue', result);
100
+ this.visible = false;
101
+ },
102
+ },
103
+ };
104
+ </script>
105
+
106
+ <style>
107
+ .tnxtdm-calendar {
108
+ display: flex;
109
+ align-items: center;
110
+
111
+ .tnxtdm-calendar__value {
112
+ min-width: 95px;
113
+ }
114
+
115
+ .tnxtdm-calendar__icon {
116
+ display: flex;
117
+ align-items: center;
118
+ color: var(--td-text-color-primary);
119
+ }
120
+ }
121
+ </style>
@@ -0,0 +1,147 @@
1
+ <template>
2
+ <div class="tnxtdm-date-time-picker">
3
+ <div class="tnxtdm-date-time-picker__value" :data-mode="mode">{{ model }}</div>
4
+ <div class="tnxtdm-date-time-picker__icon" :style="{color: iconColor}" @click="visible = true">
5
+ <t-icon name="calendar-1"/>
6
+ </div>
7
+ <t-popup v-model="visible" placement="bottom">
8
+ <t-date-time-picker
9
+ v-model="pickerValue"
10
+ :format="format"
11
+ :mode="mode"
12
+ :title="title"
13
+ :start="getDateValue(start)"
14
+ :end="getDateValue(end)"
15
+ @confirm="confirm"
16
+ @cancel="visible = false"
17
+ v-if="visible"/>
18
+ </t-popup>
19
+ </div>
20
+ </template>
21
+
22
+ <script>
23
+ export default {
24
+ name: 'TnxtdmDateTimePicker',
25
+ props: {
26
+ modelValue: String,
27
+ title: String,
28
+ defaultValue: {
29
+ type: [String, Number],
30
+ default: () => {
31
+ return new Date().getTime();
32
+ },
33
+ },
34
+ mode: {
35
+ type: String,
36
+ default: 'date',
37
+ },
38
+ showCellTitle: Boolean,
39
+ start: {
40
+ type: [String, Number],
41
+ default: '1000-01-01 00:00:00',
42
+ },
43
+ end: {
44
+ type: [String, Number],
45
+ default: '9999-12-31 23:59:59',
46
+ },
47
+ iconColor: String,
48
+ },
49
+ data() {
50
+ return {
51
+ visible: false,
52
+ model: this.modelValue || '',
53
+ pickerValue: '',
54
+ };
55
+ },
56
+ computed: {
57
+ format() {
58
+ switch (this.mode) {
59
+ case 'year':
60
+ return 'YYYY';
61
+ case 'month':
62
+ return 'YYYY-MM';
63
+ case 'date':
64
+ return 'YYYY-MM-DD';
65
+ case 'hour':
66
+ return 'YYYY-MM-DD HH';
67
+ case 'minute':
68
+ return 'YYYY-MM-DD HH:mm';
69
+ case 'second':
70
+ return 'YYYY-MM-DD HH:mm:ss';
71
+ }
72
+ return undefined;
73
+ },
74
+ pattern() {
75
+ return this.format.replace('YYYY', 'yyyy').replace('DD', 'dd');
76
+ },
77
+ },
78
+ emits: ['update:modelValue'],
79
+ watch: {
80
+ modelValue(val) {
81
+ this.model = val;
82
+ },
83
+ model(val) {
84
+ this.$emit('update:modelValue', val);
85
+ },
86
+ visible(val) {
87
+ if (val) {
88
+ this.pickerValue = this.model || this.getDateValue(this.defaultValue);
89
+ }
90
+ }
91
+ },
92
+ methods: {
93
+ getDateValue(date) {
94
+ if (date) {
95
+ return new Date(date).format(this.pattern);
96
+ }
97
+ return undefined;
98
+ },
99
+ confirm(value) {
100
+ this.model = String(value);
101
+ this.visible = false;
102
+ },
103
+ }
104
+ }
105
+ </script>
106
+
107
+ <style>
108
+ .tnxtdm-date-time-picker {
109
+ display: flex;
110
+ align-items: center;
111
+
112
+ .tnxtdm-date-time-picker__value {
113
+ display: flex;
114
+ align-items: center;
115
+
116
+ &[data-mode="year"] {
117
+ min-width: 44px;
118
+ }
119
+
120
+ &[data-mode="month"] {
121
+ min-width: 70px;
122
+ }
123
+
124
+ &[data-mode="date"] {
125
+ min-width: 95px;
126
+ }
127
+
128
+ &[data-mode="hour"] {
129
+ min-width: 119px;
130
+ }
131
+
132
+ &[data-mode="minute"] {
133
+ min-width: 141px;
134
+ }
135
+
136
+ &[data-mode="second"] {
137
+ min-width: 164px;
138
+ }
139
+ }
140
+
141
+ .tnxtdm-date-time-picker__icon {
142
+ display: flex;
143
+ align-items: center;
144
+ color: var(--td-text-color-primary);
145
+ }
146
+ }
147
+ </style>
@@ -0,0 +1,179 @@
1
+ <template>
2
+ <t-dialog
3
+ class="tnxtdm-dialog"
4
+ v-model:visible="visible"
5
+ :title="title"
6
+ :width="width"
7
+ :close-on-overlay-click="options['close-on-overlay-click']"
8
+ :close-btn="!buttons?.length"
9
+ :destroy-on-close="true"
10
+ @closed="onClosed"
11
+ >
12
+ <template #default>
13
+ <div v-if="content" v-html="content"></div>
14
+ <tnxtdm-dialog-content ref="content" v-bind="contentProps" v-else/>
15
+ </template>
16
+ <template #actions v-if="buttons?.length">
17
+ <div class="tnxtdm-dialog-footer">
18
+ <t-button v-for="(button, index) in buttons" :key="index" :theme="button.type || 'primary'"
19
+ :loading="buttonLoadings[index]" @click="btnClick(index)" block>
20
+ {{ button.caption || button.text }}
21
+ </t-button>
22
+ </div>
23
+ </template>
24
+ </t-dialog>
25
+ </template>
26
+
27
+ <script>
28
+ import DialogContent from './DialogContent.vue';
29
+
30
+ export default {
31
+ name: 'TnxtdmDialog',
32
+ components: {
33
+ 'tnxtdm-dialog-content': DialogContent,
34
+ },
35
+ props: {
36
+ id: {
37
+ type: String,
38
+ default: () => window.tnx.util.string.uuid32(),
39
+ },
40
+ modelValue: Boolean,
41
+ container: String,
42
+ title: String,
43
+ content: String,
44
+ contentProps: Object,
45
+ buttons: Array,
46
+ theme: String,
47
+ width: {
48
+ type: [Number, String],
49
+ default: '100%',
50
+ },
51
+ },
52
+ emits: ['update:modelValue', 'shown', 'closed'],
53
+ data() {
54
+ return {
55
+ visible: this.modelValue,
56
+ options: {
57
+ modal: true,
58
+ 'close-on-overlay-click': true,
59
+ onShown: undefined,
60
+ onClosed: undefined,
61
+ beforeClose: undefined,
62
+ },
63
+ buttonLoadings: [],
64
+ };
65
+ },
66
+ watch: {
67
+ modelValue(val) {
68
+ this.visible = val;
69
+ },
70
+ visible(val) {
71
+ this.$emit('update:modelValue', val);
72
+ }
73
+ },
74
+ mounted() {
75
+ this.$nextTick(() => {
76
+ if (this.$refs.content && !this.$refs.content.close) {
77
+ this.$refs.content.close = () => {
78
+ this.close();
79
+ }
80
+ }
81
+
82
+ if (typeof this.options.onShown === 'function') {
83
+ this.options.onShown.call(this);
84
+ } else {
85
+ this.$emit('shown');
86
+ }
87
+ });
88
+ },
89
+ methods: {
90
+ btnClick(index) {
91
+ const button = this.buttons[index];
92
+ if (button) {
93
+ let click = button.click;
94
+ if (typeof click === 'string') {
95
+ if (typeof this.$refs.content[click] === 'function') {
96
+ click = this.$refs.content[click];
97
+ } else {
98
+ console.error(`Method '${click}' not found in component:`, this.$refs.content);
99
+ click = null;
100
+ }
101
+ }
102
+
103
+ if (typeof click === 'function') {
104
+ let result = click.call(this.$refs.content, this.close);
105
+ if (result === 'loading') {
106
+ this.buttonLoadings[index] = true;
107
+ return;
108
+ }
109
+ if (result === false) {
110
+ return;
111
+ }
112
+ }
113
+ }
114
+ this.close();
115
+ },
116
+ close() {
117
+ return new Promise((resolve) => {
118
+ this.beforeClose(() => {
119
+ const originalOnClosed = this.options.onClosed;
120
+ this.options.onClosed = window.tnx.util.function.around(originalOnClosed, function (onClosed) {
121
+ if (onClosed) {
122
+ onClosed();
123
+ }
124
+ resolve();
125
+ });
126
+ this.visible = false;
127
+ });
128
+ });
129
+ },
130
+ beforeClose(done) {
131
+ try {
132
+ if (typeof this.options.beforeClose === 'function') {
133
+ if (this.options.beforeClose.call(this.$refs.content) === false) {
134
+ return;
135
+ }
136
+ }
137
+ done();
138
+ } catch (e) {
139
+ console.error(e);
140
+ }
141
+ },
142
+ onClosed() {
143
+ if (typeof this.options.onClosed === 'function') {
144
+ this.options.onClosed.call(this.$refs.content);
145
+ } else {
146
+ this.$emit('closed');
147
+ }
148
+ }
149
+ }
150
+ }
151
+ </script>
152
+
153
+ <style>
154
+ .tnxtdm-dialog {
155
+
156
+ &.t-dialog__wrapper.t-popup--center {
157
+ width: calc(100% - 48px);
158
+ max-width: calc(var(--max-page-width) - 48px);
159
+ }
160
+
161
+ .t-dialog__content {
162
+ padding-top: 1rem;
163
+ }
164
+
165
+ .t-dialog__close-btn {
166
+ right: 12px;
167
+ }
168
+
169
+ .t-dialog__footer {
170
+ padding: 12px 24px;
171
+
172
+ .tnxtdm-dialog-footer {
173
+ padding: 12px 0;
174
+ width: 100%;
175
+ }
176
+ }
177
+
178
+ }
179
+ </style>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <div></div>
3
+ </template>
4
+
5
+ <script>
6
+ export default {
7
+ components: {},
8
+ data() {
9
+ return {};
10
+ },
11
+ methods: {}
12
+ }
13
+ </script>
@@ -0,0 +1,197 @@
1
+ <template>
2
+ <tnxtdm-popup
3
+ class="tnxtdm-drawer"
4
+ v-model="visible"
5
+ :placement="placement"
6
+ :title="title"
7
+ :style="popupStyle"
8
+ @closed="onClosed"
9
+ >
10
+ <template #default>
11
+ <div class="tnxtdm-drawer-body">
12
+ <div v-if="content" v-html="content"></div>
13
+ <tnxtdm-drawer-content ref="content" v-bind="contentProps" v-else/>
14
+ </div>
15
+ <div class="tnxtdm-drawer-footer" v-if="buttons?.length">
16
+ <t-button v-for="(button, index) in buttons" :key="index" :theme="button.type || 'default'"
17
+ :loading="buttonLoadings[index]" @click="btnClick(index)" block>
18
+ {{ button.caption || button.text }}
19
+ </t-button>
20
+ </div>
21
+ </template>
22
+ </tnxtdm-popup>
23
+ </template>
24
+
25
+ <script>
26
+ import DrawerContent from './DrawerContent.vue';
27
+ import Popup from '../popup/Popup.vue';
28
+
29
+ export default {
30
+ name: 'TnxtdmDrawer',
31
+ components: {
32
+ 'tnxtdm-drawer-content': DrawerContent,
33
+ 'tnxtdm-popup': Popup,
34
+ },
35
+ props: {
36
+ id: {
37
+ type: String,
38
+ default: () => window.tnx.util.string.uuid32(),
39
+ },
40
+ modelValue: Boolean,
41
+ container: String,
42
+ title: String,
43
+ content: String,
44
+ contentProps: Object,
45
+ buttons: Array,
46
+ theme: String,
47
+ placement: {
48
+ type: String, // 'top' | 'left' | 'right' | 'bottom' | 'center'
49
+ default: 'bottom', // 默认底部弹出
50
+ },
51
+ },
52
+ emits: ['update:modelValue', 'shown', 'closed'],
53
+ data() {
54
+ return {
55
+ visible: false,
56
+ initialized: false,
57
+ options: {
58
+ modal: true,
59
+ onShown: undefined,
60
+ onClosed: undefined,
61
+ beforeClose: undefined,
62
+ },
63
+ buttonLoadings: [],
64
+ };
65
+ },
66
+ computed: {
67
+ popupStyle() {
68
+ const style = {};
69
+ if (this.options && this.options.width) {
70
+ style.width = this.options.width;
71
+ }
72
+ if (this.placement === 'left' || this.placement === 'right') {
73
+ style.height = '100vh';
74
+ style.maxHeight = '100vh';
75
+ style.borderRadius = '0';
76
+ }
77
+ return style;
78
+ },
79
+ },
80
+ watch: {
81
+ modelValue(val) {
82
+ this.visible = val;
83
+ },
84
+ visible(val) {
85
+ if (this.initialized) {
86
+ this.$emit('update:modelValue', val);
87
+ }
88
+ }
89
+ },
90
+ mounted() {
91
+ this.$nextTick(() => {
92
+ this.initialized = true;
93
+ this.visible = this.modelValue;
94
+ if (this.$refs.content && !this.$refs.content.close) {
95
+ this.$refs.content.close = () => {
96
+ this.close();
97
+ }
98
+ }
99
+
100
+ if (typeof this.options.onShown === 'function') {
101
+ this.options.onShown.call(this);
102
+ } else {
103
+ this.$emit('shown');
104
+ }
105
+ });
106
+ },
107
+ methods: {
108
+ btnClick(index) {
109
+ const button = this.buttons[index];
110
+ if (button) {
111
+ let click = button.click;
112
+ if (typeof click === 'string') {
113
+ if (typeof this.$refs.content[click] === 'function') {
114
+ click = this.$refs.content[click];
115
+ } else {
116
+ console.error(`Method '${click}' not found in component:`, this.$refs.content);
117
+ click = null;
118
+ }
119
+ }
120
+
121
+ if (typeof click === 'function') {
122
+ let result = click.call(this.$refs.content, this.close);
123
+ if (result === 'loading') {
124
+ this.buttonLoadings[index] = true;
125
+ return;
126
+ }
127
+ if (result === false) {
128
+ return;
129
+ }
130
+ }
131
+ }
132
+ this.close();
133
+ },
134
+ close() {
135
+ return new Promise((resolve) => {
136
+ this.beforeClose(() => {
137
+ const originalOnClosed = this.options.onClosed;
138
+ this.options.onClosed = window.tnx.util.function.around(originalOnClosed, function (onClosed) {
139
+ if (onClosed) {
140
+ onClosed();
141
+ }
142
+ resolve();
143
+ });
144
+ this.visible = false;
145
+ });
146
+ });
147
+ },
148
+ beforeClose(done) {
149
+ try {
150
+ if (typeof this.options.beforeClose === 'function') {
151
+ if (this.options.beforeClose.call(this.$refs.content) === false) {
152
+ return;
153
+ }
154
+ }
155
+ done();
156
+ } catch (e) {
157
+ console.error(e);
158
+ }
159
+ },
160
+ onClosed() {
161
+ if (typeof this.options.onClosed === 'function') {
162
+ this.options.onClosed.call(this.$refs.content);
163
+ } else {
164
+ this.$emit('closed');
165
+ }
166
+ }
167
+ }
168
+ }
169
+ </script>
170
+
171
+ <style>
172
+ .tnxtdm-drawer {
173
+ width: 75%;
174
+
175
+ .tnxtdm-drawer-body {
176
+ flex: 1;
177
+ overflow-y: auto;
178
+ }
179
+
180
+ .tnxtdm-popup-content {
181
+ display: flex;
182
+ flex-direction: column;
183
+ }
184
+
185
+ .tnxtdm-drawer-footer {
186
+ padding: 12px 1rem calc(12px + env(safe-area-inset-bottom, 0));
187
+ border-top: 1px solid var(--td-border-level-1-color);
188
+ display: flex;
189
+ flex-direction: row-reverse;
190
+
191
+ .t-button {
192
+ width: fit-content;
193
+ margin-left: 12px;
194
+ }
195
+ }
196
+ }
197
+ </style>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ <div></div>
3
+ </template>
4
+
5
+ <script>
6
+ export default {
7
+ components: {},
8
+ data() {
9
+ return {};
10
+ },
11
+ methods: {}
12
+ }
13
+ </script>