chain-saasui 1.0.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.
Files changed (53) hide show
  1. package/README.md +6 -0
  2. package/babel.config.js +13 -0
  3. package/build/webpack.common.js +54 -0
  4. package/build/webpack.components.js +69 -0
  5. package/build/webpack.demo.js +40 -0
  6. package/components/css/card.scss +19 -0
  7. package/components/css/common.scss +10 -0
  8. package/components/css/container.scss +14 -0
  9. package/components/css/detail.scss +87 -0
  10. package/components/css/dialog.scss +83 -0
  11. package/components/css/group.scss +82 -0
  12. package/components/css/index.scss +11 -0
  13. package/components/css/messagebox.scss +59 -0
  14. package/components/css/pagetable.scss +89 -0
  15. package/components/css/table.scss +0 -0
  16. package/components/css/tablebuttons.scss +15 -0
  17. package/components/css/unit.scss +25 -0
  18. package/components/src/SCard/index.vue +41 -0
  19. package/components/src/SContainer/index.vue +36 -0
  20. package/components/src/SDialog/index.vue +99 -0
  21. package/components/src/SDrawer/index.vue +95 -0
  22. package/components/src/SForm/SSelect/index.vue +108 -0
  23. package/components/src/SGroup/icon_rtsuc.png +0 -0
  24. package/components/src/SGroup/index.vue +81 -0
  25. package/components/src/SMessagebox/index.js +66 -0
  26. package/components/src/SMessagebox/messagebox.vue +85 -0
  27. package/components/src/SPage/Pagedetail.vue +114 -0
  28. package/components/src/SPage/Pagestep.vue +97 -0
  29. package/components/src/SPage/Pagetable.vue +109 -0
  30. package/components/src/STable/STablecolumn.vue +91 -0
  31. package/components/src/STable/index.vue +34 -0
  32. package/components/src/STableButtons/STableButtons.md +111 -0
  33. package/components/src/STableButtons/index.vue +96 -0
  34. package/components/src/SUnit/index.vue +75 -0
  35. package/components/src/index.js +46 -0
  36. package/gulpfile.js +20 -0
  37. package/jsconfig.json +25 -0
  38. package/lib/css/index.css +1 -0
  39. package/lib/saasui.common.js +1 -0
  40. package/package.json +82 -0
  41. package/public/favicon.ico +0 -0
  42. package/public/html/ie.html +46 -0
  43. package/public/index.html +274 -0
  44. package/public/robots.txt +2 -0
  45. package/public/template/base/Template_Account.xls +0 -0
  46. package/public/template/base/Template_Feedback.xls +0 -0
  47. package/public/template/base/Template_Team.xls +0 -0
  48. package/public/template/base/Template_Team_Member.xls +0 -0
  49. package/src/App.vue +30 -0
  50. package/src/assets/logo.png +0 -0
  51. package/src/components/HelloWorld.vue +58 -0
  52. package/src/main.js +16 -0
  53. package/vue.config.js +40 -0
@@ -0,0 +1,41 @@
1
+ <template>
2
+ <div class="saas-card">
3
+ <div class="saas-card-header">
4
+ <slot name="title">
5
+ {{ title }}
6
+ </slot>
7
+ </div>
8
+ <div class="saas-card-content">
9
+ <slot></slot>
10
+ </div>
11
+ </div>
12
+ </template>
13
+ <script>
14
+ import { omit } from "@saas/utils";
15
+ export default {
16
+ name: "SCard",
17
+ props: {
18
+ title: {
19
+ type: String,
20
+ default: "",
21
+ },
22
+ titleSub: {
23
+ type: String,
24
+ default: "",
25
+ },
26
+ },
27
+ data() {
28
+ return {};
29
+ },
30
+ computed: {
31
+
32
+ },
33
+ deactivated() {
34
+ },
35
+ methods: {
36
+
37
+ },
38
+ };
39
+ </script>
40
+ <style lang="scss" scoped>
41
+ </style>
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <div class="saas-container">
3
+ <div class="saas-container-header">
4
+ <slot name="header"></slot>
5
+ </div>
6
+ <div class="saas-container-content">
7
+ <slot></slot>
8
+ </div>
9
+ <div class="saas-container-footer">
10
+ <slot name="footer"></slot>
11
+ </div>
12
+ </div>
13
+ </template>
14
+ <script>
15
+ import { omit } from '@saas/utils';
16
+ export default {
17
+ name: 'SContainer',
18
+ props: {
19
+ title: {
20
+ type: String,
21
+ default: '',
22
+ },
23
+ titleSub: {
24
+ type: String,
25
+ default: '',
26
+ },
27
+ },
28
+ data() {
29
+ return {};
30
+ },
31
+ computed: {},
32
+ deactivated() {},
33
+ methods: {},
34
+ };
35
+ </script>
36
+ <style lang="scss" scoped></style>
@@ -0,0 +1,99 @@
1
+ <template>
2
+ <el-dialog class="saas-dialog" v-bind="bindProps" :close-on-click-modal="false" v-on="$listeners" :visible.sync="show">
3
+ <template v-if="$slots.title" slot="title">
4
+ <slot name="title"></slot>
5
+ </template>
6
+ <div class="saas-dialog-content" :class="{'saas-dialog-auto':isAuto}">
7
+ <slot></slot>
8
+ </div>
9
+ <template v-if="showFooter" slot="footer">
10
+ <slot v-if="$slots.footer" name="footer"></slot>
11
+ <div v-else>
12
+ <el-button v-if="showCancelButton" @click="handleClose">{{ cancelText }}</el-button>
13
+ <el-button v-if="showConfirmButton" :loading="loadingBtn" type="primary" @click="handleSubmit" v-preventReClick="5000">{{confirmText}}</el-button>
14
+ </div>
15
+ </template>
16
+ </el-dialog>
17
+ </template>
18
+ <script>
19
+ import { Dialog } from "element-ui";
20
+ import { omit } from "@saas/utils";
21
+ export default {
22
+ name: "SDialog",
23
+ props: {
24
+ ...Dialog.props,
25
+ showFooter: {
26
+ type: Boolean,
27
+ default: () => true,
28
+ },
29
+ width: {
30
+ type: [String, Number],
31
+ default: () => "600px",
32
+ },
33
+ // closeOnClickModal: {
34
+ // type: Boolean,
35
+ // default: () => false,
36
+ // },
37
+ loadingBtn: {
38
+ type: Boolean,
39
+ default: () => false,
40
+ },
41
+ visible: {
42
+ type: Boolean,
43
+ default: false,
44
+ },
45
+ showCancelButton: {
46
+ type: Boolean,
47
+ default: () => true,
48
+ },
49
+ showConfirmButton: {
50
+ type: Boolean,
51
+ default: () => true,
52
+ },
53
+ confirmText: {
54
+ type: String,
55
+ default() {
56
+ return this.$t("buttonGroup.sure");
57
+ },
58
+ },
59
+ cancelText: {
60
+ type: String,
61
+ default() {
62
+ return this.$t("buttonGroup.cancel");
63
+ },
64
+ },
65
+ isAuto: {
66
+ type: Boolean,
67
+ default: true,
68
+ },
69
+ },
70
+ data() {
71
+ return {};
72
+ },
73
+ computed: {
74
+ show: {
75
+ get() {
76
+ return this.visible;
77
+ },
78
+ set(val) {
79
+ this.$emit("update:visible", val);
80
+ },
81
+ },
82
+ bindProps() {
83
+ return omit(this.$props, ["visible"]);
84
+ },
85
+ },
86
+ deactivated() {
87
+ this.handleClose() // 在缓存组件时关闭弹窗
88
+ },
89
+ methods: {
90
+ handleSubmit() {
91
+ this.$emit("confirm");
92
+ },
93
+ handleClose() {
94
+ this.$emit("update:visible", false);
95
+ this.$emit("close");
96
+ },
97
+ },
98
+ };
99
+ </script>
@@ -0,0 +1,95 @@
1
+ <template>
2
+ <el-drawer class="saas-drawer" v-bind="bindProps" :wrapperClosable="false" v-on="$listeners" :visible.sync="show">
3
+ <template v-if="$slots.title" slot="title">
4
+ <slot name="title"></slot>
5
+ </template>
6
+ <div class="saas-drawer-content">
7
+ <slot></slot>
8
+ </div>
9
+ <div v-if="showFooter" class="saas-drawer-footer">
10
+ <slot v-if="$slots.footer" name="footer"></slot>
11
+ <template v-else>
12
+ <el-button v-if="showCancelButton" @click="handleClose">{{ cancelText }}</el-button>
13
+ <el-button v-if="showConfirmButton" :loading="loadingBtn" type="primary" @click="handleSubmit" v-preventReClick="5000">{{confirmText}}</el-button>
14
+ </template>
15
+ </div>
16
+ </el-drawer>
17
+ </template>
18
+ <script>
19
+ import { Drawer } from "element-ui";
20
+ import { omit } from "@saas/utils";
21
+ export default {
22
+ name: "SDrawer",
23
+ props: {
24
+ ...Drawer.props,
25
+ showFooter: {
26
+ type: Boolean,
27
+ default: () => true,
28
+ },
29
+ size: {
30
+ type: [String, Number],
31
+ default: () => "800px",
32
+ },
33
+ wrapperClosable: {
34
+ type: Boolean,
35
+ default: () => false,
36
+ },
37
+ loadingBtn: {
38
+ type: Boolean,
39
+ default: () => false,
40
+ },
41
+ appendToBody: {
42
+ type: Boolean,
43
+ default: true,
44
+ },
45
+ showCancelButton: {
46
+ type: Boolean,
47
+ default: true,
48
+ },
49
+ showConfirmButton: {
50
+ type: Boolean,
51
+ default: true,
52
+ },
53
+ confirmText: {
54
+ type: String,
55
+ default() {
56
+ return this.$t("buttonGroup.sure");
57
+ },
58
+ },
59
+ cancelText: {
60
+ type: String,
61
+ default() {
62
+ return this.$t("buttonGroup.cancel");
63
+ },
64
+ },
65
+ },
66
+ data() {
67
+ return {};
68
+ },
69
+ computed: {
70
+ show: {
71
+ get() {
72
+ return this.visible;
73
+ },
74
+ set(val) {
75
+ this.$emit("update:visible", val);
76
+ },
77
+ },
78
+ bindProps() {
79
+ return omit(this.$props, ["visible"]);
80
+ },
81
+ },
82
+ deactivated() {
83
+ this.handleClose(); // 在缓存组件时关闭弹窗
84
+ },
85
+ methods: {
86
+ handleSubmit() {
87
+ this.$emit("confirm");
88
+ },
89
+ handleClose() {
90
+ this.$emit("update:visible", false);
91
+ this.$emit("close");
92
+ },
93
+ },
94
+ };
95
+ </script>
@@ -0,0 +1,108 @@
1
+ <template>
2
+ <div class="saas-select" :class="{ 'saas-search-textbox': from === 'text' }">
3
+ <span v-if="from === 'text'" class="search-dict">{{ selectValue }}</span>
4
+ <el-select
5
+ v-else
6
+ style="width: 100%"
7
+ v-model="newValue"
8
+ :size="size"
9
+ :multiple="multiple"
10
+ :placeholder="placeholder"
11
+ v-bind="$attrs"
12
+ filterable
13
+ clearable>
14
+ <template v-for="item in options">
15
+ <!-- 如果item有options属性,说明是分组 -->
16
+ <el-option-group v-if="item.options" :key="item.value" :label="item.label">
17
+ <el-option
18
+ v-for="option in item.options"
19
+ :disabled="option.disabled"
20
+ :key="option.value"
21
+ :label="option.label"
22
+ :value="option.value"></el-option>
23
+ </el-option-group>
24
+ <!-- 否则是普通选项 -->
25
+ <el-option v-else :disabled="item.disabled" :key="item.value" :label="item.label" :value="item.value"></el-option>
26
+ </template>
27
+ </el-select>
28
+ </div>
29
+ </template>
30
+ <script>
31
+ import { isEmpty, omit } from '@saas/utils';
32
+ import { Select } from 'element-ui';
33
+ export default {
34
+ name: 'SSelect',
35
+ props: {
36
+ ...omit(Select.props, ['value', 'clearable']),
37
+ value: {
38
+ type: [String, Number, Array],
39
+ },
40
+ clearable: {
41
+ type: Boolean,
42
+ default: () => true,
43
+ },
44
+ placeholder: {
45
+ type: String,
46
+ default() {
47
+ return this.$t('common.pleaseSelect');
48
+ },
49
+ },
50
+ from: {
51
+ type: String,
52
+ default: 'select',
53
+ },
54
+ options: {
55
+ type: Array,
56
+ default: () => [],
57
+ },
58
+ },
59
+ data() {
60
+ return {};
61
+ },
62
+ computed: {
63
+ newValue: {
64
+ get() {
65
+ let value = this.multiple ? [] : '';
66
+ if (this.multiple) {
67
+ value = (this.value || []).map(m => (m != null ? String(m) : ''));
68
+ } else {
69
+ if (!isEmpty(this.value) && this.value != null) {
70
+ value = String(this.value);
71
+ }
72
+ }
73
+ return value;
74
+ },
75
+ set(val) {
76
+ this.$emit('input', val);
77
+ },
78
+ },
79
+ selectValue() {
80
+ const multiple = this.multiple;
81
+ // 扁平化所有选项,包括分组中的选项
82
+ const allOptions = this.flattenOptions(this.options || []);
83
+
84
+ if (multiple) {
85
+ const nameArr = allOptions.filter(f => this.newValue.includes(f.value)).map(m => m.label);
86
+ return nameArr.length > 1 ? `${nameArr[0]} +${nameArr.length - 1}` : nameArr[0];
87
+ } else {
88
+ const obj = allOptions.find(f => f.value == this.newValue) || {};
89
+ return obj.label || '-';
90
+ }
91
+ },
92
+ },
93
+ methods: {
94
+ flattenOptions(options) {
95
+ const result = [];
96
+ options.forEach(item => {
97
+ if (item.options) {
98
+ result.push(...item.options);
99
+ } else {
100
+ result.push(item);
101
+ }
102
+ });
103
+ return result;
104
+ },
105
+ },
106
+ };
107
+ </script>
108
+ <style lang="scss" scoped></style>
@@ -0,0 +1,81 @@
1
+ <template>
2
+ <div class="saas-group">
3
+ <div class="saas-sort-group" v-for="(group,index) in list" :key="index">
4
+ <div v-for="(item,index) in group.children" :key="index" class="saas-sort-item" :class="{active: getActive(item , group)}" @click="handleClick(item,group)">
5
+ <div class="title" :style="getSortStyle(item)">{{item.formatValue(item,data)}}</div>
6
+ <div class="text">
7
+ <span>
8
+ <slot :item="item">
9
+ {{item.label}}
10
+ <el-tooltip v-if="item.tip" :content="item.tip">
11
+ <div slot="content" v-html="item.tip"></div>
12
+ <i style="color:#A1A5B2;margin-left:4px" class="smart-info-filled"> </i>
13
+ </el-tooltip>
14
+ </slot>
15
+ </span>
16
+
17
+ </div>
18
+ <img src="./icon_rtsuc.png" alt="" srcset="">
19
+ </div>
20
+ </div>
21
+ </div>
22
+ </template>
23
+ <script>
24
+ import { omit } from "@saas/utils";
25
+ export default {
26
+ name: "SGroup",
27
+ props: {
28
+ title: {
29
+ type: String,
30
+ default: "",
31
+ },
32
+ list: {
33
+ type: Array,
34
+ default: () => [],
35
+ },
36
+ data: {
37
+ type: Object,
38
+ default: () => ({})
39
+ },
40
+ isActive: {
41
+ type: Function,
42
+ default: null
43
+ }
44
+ },
45
+ data() {
46
+ return {};
47
+ },
48
+ computed: {
49
+
50
+ },
51
+ deactivated() {
52
+ },
53
+ methods: {
54
+ getSortStyle(item) {
55
+ let obj = {};
56
+ if (item.type === "percent") {
57
+ const num = this.data[item.field];
58
+ if (num <= 30) {
59
+ obj.color = "#FF3B30";
60
+ } else if (num <= 60) {
61
+ obj.color = "#FF9900";
62
+ } else {
63
+ obj.color = "#28B86A";
64
+ }
65
+ }
66
+ return obj;
67
+ },
68
+ handleClick(item, group) {
69
+ this.$emit('tab-click', item, group)
70
+ },
71
+ getActive(item, group) {
72
+ if (this.isActive) {
73
+ return this.isActive(item, group)
74
+ }
75
+ return false;
76
+ }
77
+ },
78
+ };
79
+ </script>
80
+ <style lang="scss" scoped>
81
+ </style>
@@ -0,0 +1,66 @@
1
+ import MessageBox from './messagebox.vue';
2
+
3
+ // MessageBoxManager.js
4
+ export default class MessageBoxManager {
5
+ constructor(Vue, i18n, Component = MessageBox) {
6
+ if (!Vue) throw new Error('[MessageBox] Vue instance is required');
7
+ if (!Component) throw new Error('[MessageBox] Vue component is required');
8
+
9
+ this.Vue = Vue;
10
+ this.i18n = i18n;
11
+ this.Component = Component;
12
+ this.instance = null;
13
+ }
14
+
15
+ _t(key) {
16
+ return this.i18n ? this.i18n.t(key) : key;
17
+ }
18
+
19
+ _createInstance() {
20
+ const Constructor = this.Vue.extend(this.Component);
21
+ this.instance = new Constructor({
22
+ el: document.createElement('div'),
23
+ });
24
+ document.body.appendChild(this.instance.$el);
25
+ }
26
+
27
+ _getInstance() {
28
+ if (!this.instance) this._createInstance();
29
+ return this.instance;
30
+ }
31
+
32
+ alert(options) {
33
+ const instance = this._getInstance();
34
+ return instance.open({
35
+ ...options,
36
+ title: options.title || this._t('deletemsg.hint'),
37
+ confirmText: options.confirmText || this._t("buttonGroup.sure"),
38
+ cancelText: options.cancelText || this._t("buttonGroup.cancel"),
39
+ message: options.message,
40
+ showCancelButton: false,
41
+ });
42
+ }
43
+
44
+ confirm(options) {
45
+ const instance = this._getInstance();
46
+ return instance.open({
47
+ ...options,
48
+ title: options.title || this._t('deletemsg.hint'),
49
+ confirmText: options.confirmText || this._t("buttonGroup.sure"),
50
+ cancelText: options.cancelText || this._t("buttonGroup.cancel"),
51
+ message: options.message,
52
+ });
53
+ }
54
+
55
+ prompt(options) {
56
+ const instance = this._getInstance();
57
+ return instance.open({
58
+ ...options,
59
+ title: options.title || this._t('deletemsg.hint'),
60
+ confirmText: options.confirmText || this._t("buttonGroup.sure"),
61
+ cancelText: options.cancelText || this._t("buttonGroup.cancel"),
62
+ message: options.message,
63
+ showInput: true,
64
+ });
65
+ }
66
+ }
@@ -0,0 +1,85 @@
1
+ <template>
2
+ <transition name="el-fade-in-linear">
3
+ <div v-if="visible" class="message-box-overlay">
4
+ <div class="message-box">
5
+ <div class="message-box_main">
6
+ <div class="message-box_icon">
7
+ <span class="el-icon-warning"></span>
8
+ </div>
9
+ <div class="message-box_right">
10
+ <div class="message-box__header">
11
+ <span class="message-box__title">{{ title }}</span>
12
+ </div>
13
+ <div class="message-box__content">
14
+ <div v-if="message && dangerouslyUseHTMLString == false">{{ message }}</div>
15
+ <div v-if="message && dangerouslyUseHTMLString" v-html="message"></div>
16
+ <el-input v-if="showInput" v-model="inputValue" class="message-box__input" :placeholder="inputPlaceholder" />
17
+ </div>
18
+ </div>
19
+ </div>
20
+ <div class="message-box__footer">
21
+ <el-button v-if="showCancelButton" @click="handleCancel" size="mini">{{cancelText}}</el-button>
22
+ <el-button @click="handleConfirm" type="primary" size="mini">{{confirmText}}</el-button>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </transition>
27
+ </template>
28
+
29
+ <script>
30
+ import { isEmpty } from "@saas/utils";
31
+ export default {
32
+ name: 'SMessageBox',
33
+ props: {
34
+
35
+ },
36
+ data() {
37
+ return {
38
+ visible: false,
39
+ title: '',
40
+ message: '',
41
+ showInput: false,
42
+ inputValue: '',
43
+ inputPlaceholder: '',
44
+ showCancelButton: false,
45
+ resolve: null,
46
+ reject: null,
47
+ confirmText: "",
48
+ cancelText: "",
49
+ dangerouslyUseHTMLString: false,
50
+ };
51
+ },
52
+ methods: {
53
+ open(options) {
54
+ this.title = options.title;
55
+ this.message = options.message || '';
56
+ this.showClose = isEmpty(options.showClose) ? true : options.showClose;
57
+ this.showInput = options.showInput || false;
58
+ this.dangerouslyUseHTMLString = options.dangerouslyUseHTMLString || false;
59
+ this.inputPlaceholder = options.inputPlaceholder || '';
60
+ this.showCancelButton = isEmpty(options.showCancelButton) ? true : options.showCancelButton;
61
+ this.confirmText = options.confirmText;
62
+ this.cancelText = options.cancelText;
63
+ this.visible = true;
64
+ this.inputValue = '';
65
+
66
+ return new Promise((resolve, reject) => {
67
+ this.resolve = resolve;
68
+ this.reject = reject;
69
+ });
70
+ },
71
+ handleConfirm() {
72
+ this.visible = false;
73
+ if (this.showInput) {
74
+ this.resolve(this.inputValue);
75
+ } else {
76
+ this.resolve(true);
77
+ }
78
+ },
79
+ handleCancel() {
80
+ this.visible = false;
81
+ this.reject('cancel');
82
+ },
83
+ },
84
+ };
85
+ </script>