@truenewx/tnxvue3 3.0.9 → 3.0.11

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truenewx/tnxvue3",
3
- "version": "3.0.9",
3
+ "version": "3.0.11",
4
4
  "description": "互联网技术解决方案:Vue3扩展支持",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -25,7 +25,7 @@
25
25
  "vue-router": "~4.4.0"
26
26
  },
27
27
  "dependencies": {
28
- "@truenewx/tnxcore": "3.0.7",
28
+ "@truenewx/tnxcore": "3.0.8",
29
29
  "@element-plus/icons-vue": "2.3.1",
30
30
  "async-validator": "4.2.5",
31
31
  "mitt": "3.0.1"
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <BButton class="tnxbsv-button" :variant="type || 'outline-secondary'" :loading="loading" :disabled="loading">
2
+ <BButton class="tnxbsv-button" :variant="type || 'light'" :loading="loading" :disabled="loading">
3
3
  <i class="me-1" :class="icon" v-if="icon"></i>
4
4
  <div>
5
5
  <slot></slot>
@@ -10,7 +10,7 @@
10
10
  @focus="handleFocus"
11
11
  />
12
12
  <template #append>
13
- <BButton variant="outline-secondary" class="btn-append">
13
+ <BButton variant="light" class="btn-append">
14
14
  <i v-if="clearable && !disabled && modelValue"
15
15
  class="bi bi-x-circle me-1"
16
16
  @click.stop="clearValue">
@@ -20,7 +20,7 @@
20
20
  <component ref="content" :is="content" v-bind="contentProps" v-else></component>
21
21
  <template #footer>
22
22
  <TnxbsvButton v-for="(button, index) in buttons" :key="index"
23
- :type="button.type"
23
+ :type="button.type || 'light'"
24
24
  :loading="buttonLoadings[index]"
25
25
  @click="btnClick(index)"
26
26
  >
@@ -0,0 +1,58 @@
1
+ <template>
2
+ <div class="tnxbs-progress">
3
+ <BProgress :variant="type" :key="type" :value="value" :max="max" :show-value="showValue">
4
+ <div class="progress-bar" :style="{width: percent}">
5
+ {{ showProgress ? percent : '' }}
6
+ </div>
7
+ </BProgress>
8
+ <span class="tnxbs-progress-value" v-if="showValue">{{ value }}/{{ max }}</span>
9
+ </div>
10
+ </template>
11
+
12
+ <script>
13
+ import {BProgress} from 'bootstrap-vue-next';
14
+
15
+ export default {
16
+ name: 'TnxbsvProgress',
17
+ components: {BProgress},
18
+ props: {
19
+ type: String,
20
+ value: {
21
+ type: Number,
22
+ default: 0
23
+ },
24
+ max: Number,
25
+ precision: {
26
+ type: Number,
27
+ default: 0,
28
+ },
29
+ showValue: Boolean,
30
+ showProgress: Boolean,
31
+ },
32
+ data() {
33
+ return {};
34
+ },
35
+ computed: {
36
+ percent() {
37
+ return (this.value / this.max).toPercent(this.precision);
38
+ }
39
+ },
40
+ methods: {}
41
+ }
42
+ </script>
43
+
44
+ <style>
45
+ .tnxbs-progress {
46
+ display: flex;
47
+ align-items: center;
48
+ }
49
+
50
+ .tnxbs-progress .progress {
51
+ flex-grow: 1;
52
+ }
53
+
54
+ .tnxbs-progress .tnxbs-progress-value {
55
+ margin-left: 0.5rem;
56
+ color: var(--bs-body-color);
57
+ }
58
+ </style>
@@ -10,6 +10,10 @@
10
10
  color: var(--bs-tertiary-color) !important;
11
11
  }
12
12
 
13
+ .btn-light {
14
+ border-color: var(--bs-border-color);
15
+ }
16
+
13
17
  .link {
14
18
  cursor: pointer;
15
19
  color: var(--bs-link-color);
@@ -15,12 +15,14 @@ import FormGroup from './form/FormGroup.vue';
15
15
  import LoadingIcon from './loading-icon/LoadingIcon.vue';
16
16
  import LoadingOverlay from './loading-overlay/LoadingOverlay.vue';
17
17
  import Paged from './paged/Paged.vue';
18
+ import Progress from './progress/Progress.vue';
18
19
  import QueryForm from './query-form/QueryForm.vue';
19
20
  import QueryTable from './query-table/QueryTable.vue';
20
21
  import RegionCascader from './region-cascader/RegionCascader.vue';
21
22
  import Select from './select/Select.vue';
22
23
  import SubmitForm from './submit-form/SubmitForm.vue';
23
24
  import TagsInput from './tags-input/TagsInput.vue';
25
+ import Upload from './upload/Upload.vue';
24
26
 
25
27
  export const build = tnxvue.build;
26
28
 
@@ -34,12 +36,14 @@ export default build('tnxbsv', () => {
34
36
  FormGroup,
35
37
  LoadingIcon,
36
38
  Paged,
39
+ Progress,
37
40
  QueryForm,
38
41
  QueryTable,
39
42
  RegionCascader,
40
43
  Select,
41
44
  SubmitForm,
42
45
  TagsInput,
46
+ Upload,
43
47
  });
44
48
 
45
49
  const tnxbsv = Object.assign({}, tnxjq, tnxvue, {
@@ -51,7 +55,7 @@ export default build('tnxbsv', () => {
51
55
  let id = new Date().getTime();
52
56
  let containerId = 'dialog-container-' + id;
53
57
  let componentDefinition = Object.assign({}, Dialog,);
54
- let dialogVm = window.tnx.createVueInstance(componentDefinition, null, {
58
+ let rootProps = Object.assign({}, options, {
55
59
  modelValue: true,
56
60
  id: id,
57
61
  container: '#' + containerId,
@@ -60,6 +64,7 @@ export default build('tnxbsv', () => {
60
64
  contentProps,
61
65
  buttons,
62
66
  });
67
+ let dialogVm = window.tnx.createVueInstance(componentDefinition, null, rootProps);
63
68
  const dialogContainer = document.createElement('div');
64
69
  dialogContainer.className = 'tnxbsv-dialog-container';
65
70
  dialogContainer.id = containerId;
@@ -0,0 +1,168 @@
1
+ <template>
2
+ <div class="tnxbsv-upload">
3
+ <BOverlay :show="uploading" spinner-variant="primary" spinner-small>
4
+ <BInputGroup>
5
+ <BFormInput :value="file?.name" :placeholder="placeholder" tabindex="-1" readonly/>
6
+ <template #append>
7
+ <div class="input-group-append">
8
+ <i class="bi bi-x-circle icon-clear" @click="clear" v-if="empty"/>
9
+ <BButton :variant="buttonType" @click="toSelect">{{ buttonText }}</BButton>
10
+ </div>
11
+ </template>
12
+ </BInputGroup>
13
+ <BFormFile class="d-none" v-model="file" :accept="uploadOptions.extensions || accept"/>
14
+ </BOverlay>
15
+ <div class="tnxbsv-upload-error" v-if="errorMessage">{{ errorMessage }}</div>
16
+ </div>
17
+ </template>
18
+
19
+ <script>
20
+ import {BOverlay, BInputGroup, BFormInput, BButton, BFormFile} from 'bootstrap-vue-next';
21
+
22
+ export default {
23
+ name: 'TnxbsvUpload',
24
+ components: {BOverlay, BInputGroup, BFormInput, BButton, BFormFile,},
25
+ props: {
26
+ app: String, // 上传目标应用名称
27
+ action: {
28
+ type: String,
29
+ required: true,
30
+ },
31
+ accept: [String, Array],
32
+ uploadOptions: {
33
+ type: Object,
34
+ default: () => ({}),
35
+ },
36
+ placeholder: String,
37
+ buttonType: {
38
+ type: String,
39
+ default: 'light',
40
+ },
41
+ buttonText: {
42
+ type: String,
43
+ default: '选择文件',
44
+ },
45
+ empty: Boolean,
46
+ beforeUpload: Function,
47
+ onSuccess: Function,
48
+ onError: Function,
49
+ },
50
+ data() {
51
+ return {
52
+ file: null,
53
+ uploading: false,
54
+ errorMessage: null,
55
+ };
56
+ },
57
+ computed: {
58
+ actionUrl() {
59
+ let baseUrl;
60
+ if (this.app) {
61
+ baseUrl = window.tnx.app.rpc.getBaseUrl(this.app);
62
+ }
63
+ baseUrl = baseUrl || window.tnx.app.rpc.getDefaultBaseUrl();
64
+ return baseUrl + this.action;
65
+ },
66
+ },
67
+ watch: {
68
+ file(newFile, oldFile) {
69
+ if (newFile) {
70
+ if (!newFile.handled) {
71
+ this.uploadFile();
72
+ }
73
+ } else if (!oldFile.handled) {
74
+ oldFile.handled = true;
75
+ this.file = oldFile;
76
+ }
77
+ }
78
+ },
79
+ methods: {
80
+ toSelect() {
81
+ const $ = window.tnx.libs.$;
82
+ $('.tnxbsv-upload input[type="file"]').trigger('click')
83
+ },
84
+ clear() {
85
+ this.file.handled = true;
86
+ this.$nextTick(() => {
87
+ this.file = null;
88
+ });
89
+ },
90
+ uploadFile() {
91
+ if (this.file) {
92
+ if (this.beforeUpload && this.beforeUpload(this.file) === false) {
93
+ return;
94
+ }
95
+ const formData = new FormData();
96
+ formData.append('file', this.file);
97
+ this.uploading = true;
98
+ this.errorMessage = null;
99
+
100
+ window.tnx.app.rpc.request(this.actionUrl, {
101
+ method: 'POST',
102
+ body: formData,
103
+ timeout: 0, // 文件上传不设置超时
104
+ app: this.app, // 指定目标应用
105
+ success: result => {
106
+ if (this.onSuccess) {
107
+ this.onSuccess(result);
108
+ } else {
109
+ console.log('文件上传成功:', result);
110
+ }
111
+ this.uploading = false;
112
+ },
113
+ error: error => {
114
+ this.uploading = false;
115
+ if (this.onError && this.onError(error) === false) {
116
+ return;
117
+ }
118
+ this.errorMessage = error.message;
119
+ }
120
+ });
121
+ }
122
+ }
123
+ }
124
+ }
125
+ </script>
126
+
127
+ <style>
128
+ .tnxbsv-upload input:focus {
129
+ outline: none;
130
+ box-shadow: none;
131
+ border-color: var(--bs-border-color);
132
+ }
133
+
134
+ .tnxbsv-upload .input-group-append {
135
+ position: relative;
136
+ }
137
+
138
+ .tnxbsv-upload .input-group-append .icon-clear {
139
+ position: absolute;
140
+ right: calc(100% + 0.75rem);
141
+ top: 50%;
142
+ transform: translateY(-50%);
143
+ cursor: pointer;
144
+ z-index: 10;
145
+ color: var(--bs-tertiary-color);
146
+ }
147
+
148
+ .tnxbsv-upload .input-group-append .icon-clear:hover {
149
+ color: var(--bs-secondary-color);
150
+ }
151
+
152
+ .tnxbsv-upload .input-group-append .btn {
153
+ border-top-left-radius: 0;
154
+ border-bottom-left-radius: 0;
155
+ }
156
+
157
+ .tnxbsv-upload-error {
158
+ margin-top: 0.25rem;
159
+ color: var(--bs-danger);
160
+ font-size: 87.5%;
161
+ }
162
+
163
+ .tnxbsv-upload-placeholder {
164
+ margin-top: 0.25rem;
165
+ color: var(--bs-tertiary-color);
166
+ font-size: 87.5%;
167
+ }
168
+ </style>
package/src/tnxvue.js CHANGED
@@ -2,8 +2,8 @@
2
2
  /**
3
3
  * 基于Vue 3的扩展支持
4
4
  */
5
- // import tnxcore from '@truenewx/tnxcore';
6
- import tnxcore from '../../core/src/tnxcore';
5
+ import tnxcore from '@truenewx/tnxcore';
6
+ // import tnxcore from '../../core/src/tnxcore';
7
7
  import validator from './tnxvue-validator';
8
8
  import createRouter from './tnxvue-router';
9
9
  import Text from './text/Text.vue';
@@ -175,7 +175,7 @@ export default build('tnxvue', () => {
175
175
  } else if (type === 'close') {
176
176
  return [{
177
177
  text: '关闭',
178
- type: theme || 'default',
178
+ type: theme,
179
179
  click(close) {
180
180
  if (typeof callback === 'function') {
181
181
  return callback.call(this, close);