Merge pull request #65 from Tencent/refactor/setupscript

Refactor/setupscript
This commit is contained in:
yuyang 2022-02-19 23:10:37 +08:00 committed by GitHub
commit 9472ca622f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 1300 additions and 7462 deletions

View File

@ -11,6 +11,10 @@
"jest": true, "jest": true,
"es6": true "es6": true
}, },
"globals": {
"defineProps": "readonly",
"defineEmits": "readonly"
},
"plugins": [ "plugins": [
"vue", "vue",
"@typescript-eslint" "@typescript-eslint"

1
.gitignore vendored
View File

@ -20,3 +20,4 @@ yarn-error.log
.stylelintcache .stylelintcache
yarn.lock yarn.lock
package-lock.json package-lock.json
pnpm-lock.yaml

View File

@ -1,15 +0,0 @@
# 选择一个 Base 镜像
FROM node:16
# 设置工作目录
WORKDIR /space
# 将 by 中的文件列表 COPY 过来
COPY . .
# 根据 COPY 过来的文件进行依赖的安装
RUN npm i
# 设置好需要的环境变量
ENV NODE_PATH=/space/node_modules

View File

@ -1,20 +0,0 @@
server {
if ($request_method = HEAD) {
return 200;
}
location / {
alias /usr/share/nginx/html/;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log error;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

View File

@ -23,9 +23,9 @@
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"qrcode.vue": "^3.2.2", "qrcode.vue": "^3.2.2",
"tdesign-icons-vue-next": "^0.0.6", "tdesign-icons-vue-next": "^0.0.6",
"tdesign-vue-next": "0.7.0-alpha.0", "tdesign-vue-next": "0.8.1",
"tvision-color": "^1.3.1", "tvision-color": "^1.3.1",
"vue": "^3.1.5", "vue": "^3.2.31",
"vue-color-kit": "^1.0.5", "vue-color-kit": "^1.0.5",
"vue-router": "^4.0.11", "vue-router": "^4.0.11",
"vue3-clipboard": "^1.0.0", "vue3-clipboard": "^1.0.0",
@ -83,4 +83,4 @@
"git add ." "git add ."
] ]
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +1,19 @@
<template> <template>
<router-view :class="[mode]" /> <router-view :class="[mode]" />
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, computed, onMounted } from 'vue'; import { computed, onMounted } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import config from '@/config/style'; import config from '@/config/style';
export default defineComponent({ const store = useStore();
setup() {
const store = useStore();
const mode = computed(() => { const mode = computed(() => {
return store.getters['setting/mode']; return store.getters['setting/mode'];
}); });
onMounted(() => { onMounted(() => {
store.dispatch('setting/changeTheme', { ...config }); store.dispatch('setting/changeTheme', { ...config });
});
return {
mode,
};
},
}); });
</script> </script>
<style lang="less"> <style lang="less">

View File

@ -9,21 +9,15 @@
<user-avatar-icon v-if="product.type === 4" /> <user-avatar-icon v-if="product.type === 4" />
<laptop-icon v-if="product.type === 5" /> <laptop-icon v-if="product.type === 5" />
</div> </div>
<t-tag :theme="product.isSetup ? 'success' : 'default'" :disabled="!product.isSetup">{{ <t-tag :theme="product.isSetup ? 'success' : 'default'" :disabled="!product.isSetup">
product.isSetup ? '已启用' : '已停用' {{ product.isSetup ? '已启用' : '已停用' }}
}}</t-tag> </t-tag>
</t-row> </t-row>
<p class="list-card-item_detail--name"> <p class="list-card-item_detail--name">{{ product.name }}</p>
{{ product.name }} <p class="list-card-item_detail--desc">{{ product.description }}</p>
</p>
<p class="list-card-item_detail--desc">
{{ product.description }}
</p>
<t-row justify="space-between" align="middle" :class="cardControlClass"> <t-row justify="space-between" align="middle" :class="cardControlClass">
<div> <div>
<t-button shape="circle" :disabled="!product.isSetup"> <t-button shape="circle" :disabled="!product.isSetup">{{ typeMap[product.type - 1] }}</t-button>
{{ typeMap[product.type - 1] }}
</t-button>
<t-button shape="circle" :disabled="!product.isSetup"> <t-button shape="circle" :disabled="!product.isSetup">
<add-icon /> <add-icon />
</t-button> </t-button>
@ -52,8 +46,8 @@
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { computed, defineComponent, PropType } from 'vue'; import { computed, PropType } from 'vue';
import { import {
ShopIcon, ShopIcon,
CalendarIcon, CalendarIcon,
@ -71,63 +65,35 @@ export interface CardProductType {
name: string; name: string;
} }
export default defineComponent({ const props = defineProps({
name: 'ListCardComponent', product: {
components: { type: Object as PropType<CardProductType>,
ShopIcon,
CalendarIcon,
ServiceIcon,
UserAvatarIcon,
LaptopIcon,
MoreIcon,
AddIcon,
},
props: {
product: {
type: Object as PropType<CardProductType>,
default: () => {
return {};
},
},
},
emits: ['manage-product', 'delete-item'],
setup(props, ctx) {
const { emit } = ctx;
const cardClass = computed(() => [
'list-card-item',
{
'list-card-item__disabled': !props.product.isSetup,
},
]);
const cardLogoClass = computed(() => [
'list-card-item_detail--logo',
{
'list-card-item_detail--logo__disabled': !props.product.isSetup,
},
]);
const cardControlClass = computed(() => [
'list-card-item_detail--control',
{
'list-card-item_detail--control__disabled': !props.product.isSetup,
},
]);
return {
cardClass,
cardLogoClass,
cardControlClass,
typeMap: ['A', 'B', 'C', 'D', 'E'],
handleClickManage(product) {
emit('manage-product', product);
},
handleClickDelete(product) {
emit('delete-item', product);
},
};
}, },
}); });
const emit = defineEmits(['manage-product', 'delete-item']);
const cardClass = computed(() => ['list-card-item', { 'list-card-item__disabled': !props.product.isSetup }]);
const cardLogoClass = computed(() => [
'list-card-item_detail--logo',
{ 'list-card-item_detail--logo__disabled': !props.product.isSetup },
]);
const cardControlClass = computed(() => [
'list-card-item_detail--control',
{ 'list-card-item_detail--control__disabled': !props.product.isSetup },
]);
const typeMap = ['A', 'B', 'C', 'D', 'E'];
const handleClickManage = (product: CardProductType) => {
emit('manage-product', product);
};
const handleClickDelete = (product: CardProductType) => {
emit('delete-item', product);
};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -16,70 +16,51 @@
<div v-if="size !== 'small'" class="card-spacer-bottom" /> <div v-if="size !== 'small'" class="card-spacer-bottom" />
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, PropType, computed } from 'vue'; import { computed } from 'vue';
export default defineComponent({ const props = defineProps({
name: 'Card', title: String,
props: { subtitle: String,
title: { describe: String,
type: String as PropType<string>, compact: {
default: '', type: Boolean,
}, default: false,
subtitle: {
type: String as PropType<string>,
default: '',
},
compact: {
type: Boolean as PropType<boolean>,
default: false,
},
describe: {
type: String as PropType<string>,
default: '',
},
size: {
type: String as PropType<string>,
default: 'default',
},
border: {
type: Boolean,
default: false,
},
}, },
setup(props) { size: {
const containerCls = computed(() => { type: String,
const { compact, border } = props; default: 'default',
return ['card-container', { 'card-container-compact': compact, 'card-container--border': border }];
});
const titleCls = computed(() => {
const { size } = props;
return [
'card-title',
{
'card-title--small': size === 'small',
'card-title--default': size !== 'small',
},
];
});
const titleTextCls = computed(() => {
const { size } = props;
return [
{
'card-title__text--small': size === 'small',
'card-title__text--default': size !== 'small',
},
];
});
return {
containerCls,
titleCls,
titleTextCls,
};
}, },
border: {
type: Boolean,
default: false,
},
});
const containerCls = computed(() => {
const { compact, border } = props;
return ['card-container', { 'card-container-compact': compact, 'card-container--border': border }];
});
const titleCls = computed(() => {
const { size } = props;
return [
'card-title',
{
'card-title--small': size === 'small',
'card-title--default': size !== 'small',
},
];
});
const titleTextCls = computed(() => {
const { size } = props;
return [
{
'card-title__text--small': size === 'small',
'card-title__text--default': size !== 'small',
},
];
}); });
</script> </script>
<style lang="less"> <style lang="less">

View File

@ -1,37 +1,28 @@
<template> <template>
<div :style="style" class="color-container" /> <div :style="style" class="color-container" />
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { computed, defineComponent, PropType } from 'vue'; import { computed } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { getBrandColor } from '@/config/color'; import { getBrandColor } from '@/config/color';
const panelColor = const panelColor =
'conic-gradient(from 90deg at 50% 50%, #FF0000 -19.41deg, #FF0000 18.76deg, #FF8A00 59.32deg, #FFE600 99.87deg, #14FF00 141.65deg, #00A3FF 177.72deg, #0500FF 220.23deg, #AD00FF 260.13deg, #FF00C7 300.69deg, #FF0000 340.59deg, #FF0000 378.76deg)'; 'conic-gradient(from 90deg at 50% 50%, #FF0000 -19.41deg, #FF0000 18.76deg, #FF8A00 59.32deg, #FFE600 99.87deg, #14FF00 141.65deg, #00A3FF 177.72deg, #0500FF 220.23deg, #AD00FF 260.13deg, #FF00C7 300.69deg, #FF0000 340.59deg, #FF0000 378.76deg)';
export default defineComponent({ const props = defineProps({
name: 'Color', value: {
props: { type: String,
value: {
type: String as PropType<string>,
default: 'default',
},
}, },
setup(props) { });
const store = useStore();
const style = computed(() => { const store = useStore();
const { value } = props;
const { colorList } = store.state.setting;
return {
background: value !== 'dynamic' ? getBrandColor(value, colorList)['@brand-color'] : panelColor,
};
});
return { const style = computed(() => {
style, const { value } = props;
}; const { colorList } = store.state.setting;
}, return {
background: value !== 'dynamic' ? getBrandColor(value, colorList)['@brand-color'] : panelColor,
};
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -8,55 +8,36 @@
<slot /> <slot />
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, PropType, computed } from 'vue'; import { computed } from 'vue';
import Result403Icon from '@/assets/assets-result-403.svg?component'; import Result403Icon from '@/assets/assets-result-403.svg?component';
import Result404Icon from '@/assets/assets-result-404.svg?component'; import Result404Icon from '@/assets/assets-result-404.svg?component';
import Result500Icon from '@/assets/assets-result-500.svg?component'; import Result500Icon from '@/assets/assets-result-500.svg?component';
import ResultIeIcon from '@/assets/assets-result-ie.svg?component'; import ResultIeIcon from '@/assets/assets-result-ie.svg?component';
import ResultWifiIcon from '@/assets/assets-result-wifi.svg?component'; import ResultWifiIcon from '@/assets/assets-result-wifi.svg?component';
export default defineComponent({ const props = defineProps({
name: 'Result', bgUrl: String,
props: { title: String,
bgUrl: { tip: String,
type: String as PropType<string>, type: String,
default: '', });
},
title: { const dynamicComponent = computed(() => {
type: String as PropType<string>, switch (props.type) {
default: '', case '403':
}, return Result403Icon;
tip: { case '404':
type: String as PropType<string>, return Result404Icon;
default: '', case '500':
}, return Result500Icon;
type: { case 'ie':
type: String as PropType<string>, return ResultIeIcon;
default: '', case 'wifi':
}, return ResultWifiIcon;
}, default:
setup(props) { return Result403Icon;
const dynamicComponent = computed(() => { }
switch (props.type) {
case '403':
return Result403Icon;
case '404':
return Result404Icon;
case '500':
return Result500Icon;
case 'ie':
return ResultIeIcon;
case 'wifi':
return ResultWifiIcon;
default:
return Result403Icon;
}
});
return {
dynamicComponent,
};
},
}); });
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -1,35 +1,27 @@
<template> <template>
<img :class="className" :src="url" /> <img :class="className" :src="url" />
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, computed, PropType } from 'vue'; import { computed } from 'vue';
export default defineComponent({ const props = defineProps({
name: 'Thumbnail', url: String,
props: { type: {
url: { type: String,
type: String as PropType<string>, default: 'layout',
default: '',
},
type: {
type: String as PropType<string>,
default: 'layout',
},
},
setup(props) {
const className = computed(() => {
const { type } = props;
return [
'thumbnail-container',
{
'thumbnail-circle': type === 'circle',
'thumbnail-layout': type === 'layout',
},
];
});
return { className };
}, },
}); });
const className = computed(() => {
const { type } = props;
return [
'thumbnail-container',
{
'thumbnail-circle': type === 'circle',
'thumbnail-layout': type === 'layout',
},
];
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import url('@/style/index.less'); @import url('@/style/index.less');

View File

@ -20,46 +20,31 @@
<span>{{ describe }}</span> <span>{{ describe }}</span>
</span> </span>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, computed, PropType } from 'vue'; import { computed } from 'vue';
export default defineComponent({ const props = defineProps({
name: 'Trend', type: String,
props: { describe: [String, Number],
type: { isReverseColor: {
type: String as PropType<string>, type: Boolean,
default: '', default: false,
},
describe: {
type: [String, Number] as PropType<string | number>,
default: '',
},
isReverseColor: {
type: Boolean as PropType<boolean>,
default: false,
},
},
setup(props) {
const containerCls = computed(() => {
const { isReverseColor, type } = props;
return [
'trend-container',
{
'trend-container__reverse': isReverseColor,
'trend-container__up': !isReverseColor && type === 'up',
'trend-container__down': !isReverseColor && type === 'down',
},
];
});
const iconCls = computed(() => ['trend-icon-container']);
return {
containerCls,
iconCls,
};
}, },
}); });
const containerCls = computed(() => {
const { isReverseColor, type } = props;
return [
'trend-container',
{
'trend-container__reverse': isReverseColor,
'trend-container__up': !isReverseColor && type === 'up',
'trend-container__down': !isReverseColor && type === 'down',
},
];
});
const iconCls = computed(() => ['trend-icon-container']);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -6,37 +6,25 @@
</t-breadcrumb> </t-breadcrumb>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, computed } from 'vue'; import { computed } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
export default defineComponent({ const crumbs = computed(() => {
name: 'TdesignStarterBreadcrumb', const route = useRoute();
props: {
isVisible: Boolean,
},
setup() {
const crumbs = computed(() => {
const route = useRoute();
const pathArray = route.path.split('/'); const pathArray = route.path.split('/');
pathArray.shift(); pathArray.shift();
const breadcrumbs = pathArray.reduce((breadcrumbArray, path, idx) => { const breadcrumbs = pathArray.reduce((breadcrumbArray, path, idx) => {
breadcrumbArray.push({ breadcrumbArray.push({
path, path,
to: breadcrumbArray[idx - 1] ? `/${breadcrumbArray[idx - 1].path}/${path}` : `/${path}`, to: breadcrumbArray[idx - 1] ? `/${breadcrumbArray[idx - 1].path}/${path}` : `/${path}`,
title: route.matched[idx].meta.title || path, title: route.matched[idx].meta.title || path,
});
return breadcrumbArray;
}, []);
return breadcrumbs;
}); });
return breadcrumbArray;
return { }, []);
crumbs, return breadcrumbs;
};
},
}); });
</script> </script>
<style scoped> <style scoped>

View File

@ -2,18 +2,8 @@
<div :class="prefix + '-footer'">Copyright @ 2021-{{ new Date().getFullYear() }} Tencent. All Rights Reserved</div> <div :class="prefix + '-footer'">Copyright @ 2021-{{ new Date().getFullYear() }} Tencent. All Rights Reserved</div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue';
import { prefix } from '@/config/global'; import { prefix } from '@/config/global';
export default defineComponent({
name: `${prefix}-footer`,
setup() {
return {
prefix,
};
},
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -63,8 +63,8 @@
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, PropType, computed, ref } from 'vue'; import { PropType, computed } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { useRouter, useRoute } from 'vue-router'; import { useRouter, useRoute } from 'vue-router';
@ -76,122 +76,89 @@ import Notice from './Notice.vue';
import Search from './Search.vue'; import Search from './Search.vue';
import MenuContent from './MenuContent'; import MenuContent from './MenuContent';
export default defineComponent({ const props = defineProps({
components: { theme: {
tLogoFull, type: String,
Notice, default: '',
Search,
MenuContent,
}, },
props: { layout: {
theme: { type: String,
type: String as PropType<string>, default: 'top',
default: '',
},
layout: {
type: String as PropType<string>,
default: 'top',
},
showLogo: {
type: Boolean as PropType<boolean>,
default: true,
},
menu: {
type: Array as PropType<MenuRoute[]>,
default: () => [],
},
isFixed: {
type: Boolean as PropType<boolean>,
default: false,
},
isCompact: {
type: Boolean as PropType<boolean>,
default: false,
},
maxLevel: {
type: Number as PropType<number>,
default: 3,
},
}, },
setup(props) { showLogo: {
const store = useStore(); type: Boolean,
const router = useRouter(); default: true,
},
const toggleSettingPanel = () => { menu: {
store.commit('setting/toggleSettingPanel', true); type: Array as PropType<MenuRoute[]>,
}; default: () => [],
},
const active = computed(() => { isFixed: {
const route = useRoute(); type: Boolean,
if (!route.path) { default: false,
return ''; },
} isCompact: {
return route.path type: Boolean,
.split('/') default: false,
.filter((item, index) => index <= props.maxLevel && index > 0) },
.map((item) => `/${item}`) maxLevel: {
.join(''); type: Number,
}); default: 3,
const showMenu = computed(() => !(props.layout === 'mix' && props.showLogo));
const layoutCls = computed(() => [`${prefix}-header-layout`]);
const menuCls = computed(() => {
const { isFixed, layout, isCompact } = props;
return [
{
[`${prefix}-header-menu`]: !isFixed,
[`${prefix}-header-menu-fixed`]: isFixed,
[`${prefix}-header-menu-fixed-side`]: layout === 'side' && isFixed,
[`${prefix}-header-menu-fixed-side-compact`]: layout === 'side' && isFixed && isCompact,
},
];
});
const userVisible = ref(false);
const userVisibleChange = (value: boolean) => {
userVisible.value = value;
};
const changeCollapsed = () => {
store.commit('setting/toggleSidebarCompact');
};
const isSidebarCompact = computed(() => store.state.setting.isSidebarCompact);
const handleNav = (url) => {
router.push(url);
};
const handleLogout = () => {
router.push(`/login?redirect=${router.currentRoute.value.fullPath}`);
};
const navToGitHub = () => {
window.open('https://github.com/tencent/tdesign-vue-next-starter');
};
const navToHelper = () => {
window.open('http://tdesign.tencent.com/starter/docs/get-started');
};
return {
isSidebarCompact,
toggleSettingPanel,
active,
showMenu,
layoutCls,
userVisible,
userVisibleChange,
menuCls,
changeCollapsed,
handleNav,
handleLogout,
navToGitHub,
navToHelper,
};
}, },
}); });
const store = useStore();
const router = useRouter();
const toggleSettingPanel = () => {
store.commit('setting/toggleSettingPanel', true);
};
const active = computed(() => {
const route = useRoute();
if (!route.path) {
return '';
}
return route.path
.split('/')
.filter((item, index) => index <= props.maxLevel && index > 0)
.map((item) => `/${item}`)
.join('');
});
const layoutCls = computed(() => [`${prefix}-header-layout`]);
const menuCls = computed(() => {
const { isFixed, layout, isCompact } = props;
return [
{
[`${prefix}-header-menu`]: !isFixed,
[`${prefix}-header-menu-fixed`]: isFixed,
[`${prefix}-header-menu-fixed-side`]: layout === 'side' && isFixed,
[`${prefix}-header-menu-fixed-side-compact`]: layout === 'side' && isFixed && isCompact,
},
];
});
const changeCollapsed = () => {
store.commit('setting/toggleSidebarCompact');
};
const handleNav = (url) => {
router.push(url);
};
const handleLogout = () => {
router.push(`/login?redirect=${router.currentRoute.value.fullPath}`);
};
const navToGitHub = () => {
window.open('https://github.com/tencent/tdesign-vue-next-starter');
};
const navToHelper = () => {
window.open('http://tdesign.tencent.com/starter/docs/get-started');
};
</script> </script>
<style lang="less"> <style lang="less">
@import '@/style/variables.less'; @import '@/style/variables.less';

View File

@ -45,47 +45,37 @@
</t-popup> </t-popup>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, computed } from 'vue'; import { computed } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { NotificationItem } from '@/interface'; import { NotificationItem } from '@/interface';
export default defineComponent({ const router = useRouter();
setup() { const store = useStore();
const router = useRouter(); const { msgData } = store.state.notification;
const store = useStore();
const { msgData } = store.state.notification;
const unreadMsg = computed(() => store.getters['notification/unreadMsg']); const unreadMsg = computed(() => store.getters['notification/unreadMsg']);
const setRead = (type: string, item?: NotificationItem) => { const setRead = (type: string, item?: NotificationItem) => {
const changeMsg = msgData; const changeMsg = msgData;
if (type === 'all') { if (type === 'all') {
changeMsg.forEach((e: NotificationItem) => { changeMsg.forEach((e: NotificationItem) => {
e.status = false; e.status = false;
}); });
} else { } else {
changeMsg.forEach((e: NotificationItem) => { changeMsg.forEach((e: NotificationItem) => {
if (e.id === item?.id) { if (e.id === item?.id) {
e.status = false; e.status = false;
}
});
} }
store.commit('notification/setMsgData', changeMsg); });
}; }
store.commit('notification/setMsgData', changeMsg);
};
const goDetail = () => { const goDetail = () => {
router.push('/detail/secondary'); router.push('/detail/secondary');
}; };
return {
goDetail,
unreadMsg,
setRead,
};
},
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -36,31 +36,21 @@
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref, PropType } from 'vue'; import { ref } from 'vue';
export default defineComponent({ const layout = defineProps({
props: { type: String,
layout: {
type: String as PropType<string>,
},
},
setup() {
const isSearchFocus = ref(false);
const searchData = ref('');
const changeSearchFocus = (value: boolean) => {
if (!value) {
searchData.value = '';
}
isSearchFocus.value = value;
};
return {
isSearchFocus,
searchData,
changeSearchFocus,
};
},
}); });
const isSearchFocus = ref(false);
const searchData = ref('');
const changeSearchFocus = (value: boolean) => {
if (!value) {
searchData.value = '';
}
isSearchFocus.value = value;
};
</script> </script>
<style lang="less"> <style lang="less">
@import '@/style/variables.less'; @import '@/style/variables.less';

View File

@ -90,8 +90,8 @@
</div> </div>
</t-drawer> </t-drawer>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref, computed, watch, onMounted } from 'vue'; import { ref, computed, watch, onMounted, watchEffect } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { ColorPicker } from 'vue-color-kit'; import { ColorPicker } from 'vue-color-kit';
import { MessagePlugin, PopupVisibleChangeContext } from 'tdesign-vue-next'; import { MessagePlugin, PopupVisibleChangeContext } from 'tdesign-vue-next';
@ -118,133 +118,110 @@ const MODE_OPTIONS = [
{ type: 'auto', text: '跟随系统' }, { type: 'auto', text: '跟随系统' },
]; ];
export default defineComponent({ const formData = ref({ ...STYLE_CONFIG });
name: 'DefaultLayoutSetting', const store = useStore();
components: { Thumbnail, ColorContainer, ColorPicker }, const colors = ref();
setup() { const isColoPickerDisplay = ref(false);
const formData = ref({ ...STYLE_CONFIG });
const store = useStore();
const colors = ref();
const isColoPickerDisplay = ref(false);
const showSettingPanel = computed({ const showSettingPanel = computed({
get() { get() {
return store.state.setting.showSettingPanel; return store.state.setting.showSettingPanel;
},
set(newVal) {
store.commit('setting/toggleSettingPanel', newVal);
},
});
const mode = computed(() => {
return store.getters['setting/mode'];
});
watch(
() => colors.value,
(newColor) => {
const { hex } = newColor;
const { setting } = store.state;
// hex
const newPalette = Color.getPaletteByGradation({
colors: [hex],
step: 10,
})[0];
const { mode } = store.state.setting;
const colorMap = generateColorMap(hex, newPalette, mode);
store.commit('setting/addColor', { [hex]: colorMap });
insertThemeStylesheet(hex, colorMap, mode);
store.dispatch('setting/changeTheme', { ...setting, brandTheme: hex });
},
);
const changeColor = (val) => {
const { hex } = val;
const { setting } = store.state;
// hex
const newPalette = Color.getPaletteByGradation({
colors: [hex],
step: 10,
})[0];
const { mode } = store.state.setting;
const colorMap = generateColorMap(hex, newPalette, mode);
store.commit('setting/addColor', { [hex]: colorMap });
insertThemeStylesheet(hex, colorMap, mode);
store.dispatch('setting/changeTheme', { ...setting, brandTheme: hex });
};
onMounted(() => {
document.querySelector('.dynamic-color-btn').addEventListener('click', () => {
isColoPickerDisplay.value = true;
});
});
const onPopupVisibleChange = (visible: boolean, context: PopupVisibleChangeContext) => {
if (!visible && context.trigger === 'document') {
isColoPickerDisplay.value = visible;
}
};
const handleCopy = () => {
const text = JSON.stringify(formData.value, null, 4);
const { toClipboard } = useClipboard();
toClipboard(text)
.then(() => {
MessagePlugin.closeAll();
MessagePlugin.success('复制成功');
})
.catch(() => {
MessagePlugin.closeAll();
MessagePlugin.error('复制失败');
});
};
const getModeIcon = (mode: string) => {
if (mode === 'light') {
return SettingLightIcon;
}
if (mode === 'dark') {
return SettingDarkIcon;
}
return SettingAutoIcon;
};
const handleCloseDrawer = () => {
store.commit('setting/toggleSettingPanel', false);
};
return {
mode,
changeColor,
isColoPickerDisplay,
onPopupVisibleChange,
MODE_OPTIONS,
LAYOUT_OPTION,
COLOR_OPTIONS,
formData,
showSettingPanel,
handleCopy,
getModeIcon,
handleCloseDrawer,
getThumbnailUrl(name: string): string {
return `https://tdesign.gtimg.com/tdesign-pro/setting/${name}.png`;
},
};
}, },
watch: { set(newVal) {
formData: { store.commit('setting/toggleSettingPanel', newVal);
handler(newVal) {
this.$store.dispatch('setting/changeTheme', newVal);
},
deep: true,
},
}, },
}); });
const mode = computed(() => {
return store.getters['setting/mode'];
});
watch(
() => colors.value,
(newColor) => {
const { hex } = newColor;
const { setting } = store.state;
// hex
const newPalette = Color.getPaletteByGradation({
colors: [hex],
step: 10,
})[0];
const { mode } = store.state.setting;
const colorMap = generateColorMap(hex, newPalette, mode);
store.commit('setting/addColor', { [hex]: colorMap });
insertThemeStylesheet(hex, colorMap, mode);
store.dispatch('setting/changeTheme', { ...setting, brandTheme: hex });
},
);
const changeColor = (val) => {
const { hex } = val;
const { setting } = store.state;
// hex
const newPalette = Color.getPaletteByGradation({
colors: [hex],
step: 10,
})[0];
const { mode } = store.state.setting;
const colorMap = generateColorMap(hex, newPalette, mode);
store.commit('setting/addColor', { [hex]: colorMap });
insertThemeStylesheet(hex, colorMap, mode);
store.dispatch('setting/changeTheme', { ...setting, brandTheme: hex });
};
onMounted(() => {
document.querySelector('.dynamic-color-btn').addEventListener('click', () => {
isColoPickerDisplay.value = true;
});
});
const onPopupVisibleChange = (visible: boolean, context: PopupVisibleChangeContext) => {
if (!visible && context.trigger === 'document') {
isColoPickerDisplay.value = visible;
}
};
const handleCopy = () => {
const text = JSON.stringify(formData.value, null, 4);
const { toClipboard } = useClipboard();
toClipboard(text)
.then(() => {
MessagePlugin.closeAll();
MessagePlugin.success('复制成功');
})
.catch(() => {
MessagePlugin.closeAll();
MessagePlugin.error('复制失败');
});
};
const getModeIcon = (mode: string) => {
if (mode === 'light') {
return SettingLightIcon;
}
if (mode === 'dark') {
return SettingDarkIcon;
}
return SettingAutoIcon;
};
const handleCloseDrawer = () => {
store.commit('setting/toggleSettingPanel', false);
};
const getThumbnailUrl = (name: string): string => {
return `https://tdesign.gtimg.com/tdesign-pro/setting/${name}.png`;
};
watchEffect(() => {
store.dispatch('setting/changeTheme', formData.value);
});
</script> </script>
<style lang="less"> <style lang="less">
@import '@/style/variables'; @import '@/style/variables';

View File

@ -2,7 +2,7 @@
<div> <div>
<t-row :gutter="[16, 16]"> <t-row :gutter="[16, 16]">
<t-col v-for="(item, index) in PANE_LIST" :key="item.title" :xs="6" :xl="3"> <t-col v-for="(item, index) in PANE_LIST" :key="item.title" :xs="6" :xl="3">
<card :subtitle="item.title" :style="{ height: '168px' }" :class="{ 'main-color': index == 0 }" size="small"> <card :subtitle="item.title" :style="{ height: '168px' }" :class="{ 'main-color': index == 0 }">
<div class="dashboard-item"> <div class="dashboard-item">
<div class="dashboard-item-top"> <div class="dashboard-item-top">
<span :style="{ fontSize: `${resizeTime * 36}px` }">{{ item.number }}</span> <span :style="{ fontSize: `${resizeTime * 36}px` }">{{ item.number }}</span>
@ -202,8 +202,8 @@
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, onMounted, watch, ref, onUnmounted, nextTick, computed } from 'vue'; import { onMounted, watch, ref, onUnmounted, nextTick, computed } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
@ -241,169 +241,150 @@ const getThisMonth = (checkedValues?: string[]) => {
return `${date.getFullYear()}-${startMonth}${date2.getFullYear()}-${endMonth}`; return `${date.getFullYear()}-${startMonth}${date2.getFullYear()}-${endMonth}`;
}; };
export default defineComponent({ const store = useStore();
name: 'DashboardBase', const resizeTime = ref(1);
components: {
Card,
Trend,
},
setup() {
const store = useStore();
const resizeTime = ref(1);
const chartColors = computed(() => store.state.setting.chartColors); const chartColors = computed(() => store.state.setting.chartColors);
// moneyCharts // moneyCharts
let moneyContainer: HTMLElement; let moneyContainer: HTMLElement;
let moneyChart: echarts.ECharts; let moneyChart: echarts.ECharts;
const renderMoneyChart = () => { const renderMoneyChart = () => {
if (!moneyContainer) { if (!moneyContainer) {
moneyContainer = document.getElementById('moneyContainer'); moneyContainer = document.getElementById('moneyContainer');
} }
moneyChart = echarts.init(moneyContainer); moneyChart = echarts.init(moneyContainer);
moneyChart.setOption(constructInitDashboardDataset('line')); moneyChart.setOption(constructInitDashboardDataset('line'));
}; };
// refundCharts // refundCharts
let refundContainer: HTMLElement; let refundContainer: HTMLElement;
let refundChart: echarts.ECharts; let refundChart: echarts.ECharts;
const renderRefundChart = () => { const renderRefundChart = () => {
if (!refundContainer) { if (!refundContainer) {
refundContainer = document.getElementById('refundContainer'); refundContainer = document.getElementById('refundContainer');
} }
refundChart = echarts.init(refundContainer); refundChart = echarts.init(refundContainer);
refundChart.setOption(constructInitDashboardDataset('bar')); refundChart.setOption(constructInitDashboardDataset('bar'));
}; };
// stokeCharts // stokeCharts
let stokeContainer: HTMLElement; let stokeContainer: HTMLElement;
let stokeChart: echarts.ECharts; let stokeChart: echarts.ECharts;
const renderStokeChart = () => { const renderStokeChart = () => {
if (!stokeContainer) { if (!stokeContainer) {
stokeContainer = document.getElementById('stokeContainer'); stokeContainer = document.getElementById('stokeContainer');
} }
stokeChart = echarts.init(stokeContainer); stokeChart = echarts.init(stokeContainer);
stokeChart.setOption(constructInitDataset({ dateTime: LAST_7_DAYS, ...chartColors.value })); stokeChart.setOption(constructInitDataset({ dateTime: LAST_7_DAYS, ...chartColors.value }));
}; };
// monitorChart // monitorChart
let monitorContainer: HTMLElement; let monitorContainer: HTMLElement;
let monitorChart: echarts.ECharts; let monitorChart: echarts.ECharts;
const renderMonitorChart = () => { const renderMonitorChart = () => {
if (!monitorContainer) { if (!monitorContainer) {
monitorContainer = document.getElementById('monitorContainer'); monitorContainer = document.getElementById('monitorContainer');
} }
monitorChart = echarts.init(monitorContainer); monitorChart = echarts.init(monitorContainer);
monitorChart.setOption(getLineChartDataSet({ ...chartColors.value })); monitorChart.setOption(getLineChartDataSet({ ...chartColors.value }));
}; };
// monitorChart // monitorChart
let countContainer: HTMLElement; let countContainer: HTMLElement;
let countChart: echarts.ECharts; let countChart: echarts.ECharts;
const renderCountChart = () => { const renderCountChart = () => {
if (!countContainer) { if (!countContainer) {
countContainer = document.getElementById('countContainer'); countContainer = document.getElementById('countContainer');
} }
countChart = echarts.init(countContainer); countChart = echarts.init(countContainer);
countChart.setOption(getPieChartDataSet(chartColors.value)); countChart.setOption(getPieChartDataSet(chartColors.value));
}; };
const renderCharts = () => { const renderCharts = () => {
renderMoneyChart(); renderMoneyChart();
renderRefundChart(); renderRefundChart();
renderStokeChart(); renderStokeChart();
renderMonitorChart(); renderMonitorChart();
renderCountChart(); renderCountChart();
}; };
// chartSize update // chartSize update
const updateContainer = () => { const updateContainer = () => {
if (document.documentElement.clientWidth >= 1400 && document.documentElement.clientWidth < 1920) { if (document.documentElement.clientWidth >= 1400 && document.documentElement.clientWidth < 1920) {
resizeTime.value = Number((document.documentElement.clientWidth / 2080).toFixed(2)); resizeTime.value = Number((document.documentElement.clientWidth / 2080).toFixed(2));
} else if (document.documentElement.clientWidth < 1080) { } else if (document.documentElement.clientWidth < 1080) {
resizeTime.value = Number((document.documentElement.clientWidth / 1080).toFixed(2)); resizeTime.value = Number((document.documentElement.clientWidth / 1080).toFixed(2));
} else { } else {
resizeTime.value = 1; resizeTime.value = 1;
} }
moneyChart.resize({ moneyChart.resize({
width: resizeTime.value * 120, width: resizeTime.value * 120,
height: resizeTime.value * 66, height: resizeTime.value * 66,
}); });
refundChart.resize({ refundChart.resize({
width: resizeTime.value * 120, width: resizeTime.value * 120,
height: resizeTime.value * 42, height: resizeTime.value * 42,
}); });
stokeChart.resize({ stokeChart.resize({
width: stokeContainer.clientWidth, width: stokeContainer.clientWidth,
height: stokeContainer.clientHeight, height: stokeContainer.clientHeight,
}); });
monitorChart.resize({ monitorChart.resize({
width: monitorContainer.clientWidth, width: monitorContainer.clientWidth,
height: resizeTime.value * 326, height: resizeTime.value * 326,
}); });
countChart.resize({ countChart.resize({
width: resizeTime.value * 326, width: resizeTime.value * 326,
height: resizeTime.value * 326, height: resizeTime.value * 326,
}); });
}; };
onMounted(() => { onMounted(() => {
renderCharts(); renderCharts();
nextTick(() => { nextTick(() => {
updateContainer(); updateContainer();
}); });
window.addEventListener('resize', updateContainer, false); window.addEventListener('resize', updateContainer, false);
});
onUnmounted(() => {
window.removeEventListener('resize', updateContainer);
});
const currentMonth = ref(getThisMonth());
watch(
() => store.state.setting.brandTheme,
() => {
changeChartsTheme([refundChart, stokeChart, monitorChart, countChart]);
},
);
watch(
() => store.state.setting.mode,
() => {
[moneyChart, refundChart, stokeChart, monitorChart, countChart].forEach((item) => {
item.dispose();
});
renderCharts();
},
);
return {
resizeTime,
currentMonth,
LAST_7_DAYS,
PANE_LIST,
BUY_TEND_LIST,
SALE_TEND_LIST,
SALE_COLUMNS,
BUY_COLUMNS,
onCurrencyChange(checkedValues: string[]) {
currentMonth.value = getThisMonth(checkedValues);
monitorChart.setOption(getLineChartDataSet({ dateTime: checkedValues, ...chartColors.value }));
},
onStokeDataChange(checkedValues: string[]) {
stokeChart.setOption(constructInitDataset({ dateTime: checkedValues, ...chartColors.value }));
},
rehandleClickOp(val: MouseEvent) {
console.log(val);
},
getRankClass(index: number) {
return ['dashboard-rank', { 'dashboard-rank__top': index < 3 }];
},
};
},
}); });
onUnmounted(() => {
window.removeEventListener('resize', updateContainer);
});
const currentMonth = ref(getThisMonth());
watch(
() => store.state.setting.brandTheme,
() => {
changeChartsTheme([refundChart, stokeChart, monitorChart, countChart]);
},
);
watch(
() => store.state.setting.mode,
() => {
[moneyChart, refundChart, stokeChart, monitorChart, countChart].forEach((item) => {
item.dispose();
});
renderCharts();
},
);
const onCurrencyChange = (checkedValues: string[]) => {
currentMonth.value = getThisMonth(checkedValues);
monitorChart.setOption(getLineChartDataSet({ dateTime: checkedValues, ...chartColors.value }));
};
const onStokeDataChange = (checkedValues: string[]) => {
stokeChart.setOption(constructInitDataset({ dateTime: checkedValues, ...chartColors.value }));
};
const rehandleClickOp = (val: MouseEvent) => {
console.log(val);
};
const getRankClass = (index: number) => {
return ['dashboard-rank', { 'dashboard-rank__top': index < 3 }];
};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import './index.less'; @import './index.less';

View File

@ -57,8 +57,8 @@
</card> </card>
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, nextTick, onMounted, onUnmounted, watch, computed } from 'vue'; import { nextTick, onMounted, onUnmounted, watch, computed } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
@ -76,91 +76,77 @@ import Card from '@/components/card/index.vue';
echarts.use([GridComponent, LegendComponent, TooltipComponent, LineChart, ScatterChart, CanvasRenderer]); echarts.use([GridComponent, LegendComponent, TooltipComponent, LineChart, ScatterChart, CanvasRenderer]);
export default defineComponent({ const store = useStore();
name: 'DashboardDetail', const chartColors = computed(() => store.state.setting.chartColors);
components: { // lineChart logic
Card, let lineContainer: HTMLElement;
Trend, let lineChart: echarts.ECharts;
ProductCard, const renderLineChart = () => {
}, lineContainer = document.getElementById('lineContainer');
setup() { lineChart = echarts.init(lineContainer);
const store = useStore(); lineChart.setOption(getFolderLineDataSet({ ...chartColors.value }));
const chartColors = computed(() => store.state.setting.chartColors); };
// lineChart logic
let lineContainer: HTMLElement;
let lineChart: echarts.ECharts;
const renderLineChart = () => {
lineContainer = document.getElementById('lineContainer');
lineChart = echarts.init(lineContainer);
lineChart.setOption(getFolderLineDataSet({ ...chartColors.value }));
};
// scatterChart logic // scatterChart logic
let scatterContainer: HTMLElement; let scatterContainer: HTMLElement;
let scatterChart: echarts.ECharts; let scatterChart: echarts.ECharts;
const renderScatterChart = () => { const renderScatterChart = () => {
scatterContainer = document.getElementById('scatterContainer'); scatterContainer = document.getElementById('scatterContainer');
scatterChart = echarts.init(scatterContainer); scatterChart = echarts.init(scatterContainer);
scatterChart.setOption(getScatterDataSet({ ...chartColors.value })); scatterChart.setOption(getScatterDataSet({ ...chartColors.value }));
}; };
// chartSize update // chartSize update
const updateContainer = () => { const updateContainer = () => {
lineChart?.resize({ lineChart?.resize({
width: lineContainer.clientWidth, width: lineContainer.clientWidth,
height: lineContainer.clientHeight, height: lineContainer.clientHeight,
}); });
scatterChart?.resize({ scatterChart?.resize({
width: scatterContainer.clientWidth, width: scatterContainer.clientWidth,
height: scatterContainer.clientHeight, height: scatterContainer.clientHeight,
}); });
}; };
const renderCharts = () => { const renderCharts = () => {
renderScatterChart(); renderScatterChart();
renderLineChart(); renderLineChart();
}; };
onMounted(() => { onMounted(() => {
renderCharts(); renderCharts();
window.addEventListener('resize', updateContainer, false); window.addEventListener('resize', updateContainer, false);
nextTick(() => { nextTick(() => {
updateContainer(); updateContainer();
}); });
});
onUnmounted(() => {
window.removeEventListener('resize', updateContainer);
});
watch(
() => store.state.setting.mode,
() => {
renderCharts();
},
);
watch(
() => store.state.setting.brandTheme,
() => {
changeChartsTheme([lineChart, scatterChart]);
},
);
return {
LAST_7_DAYS,
PRODUCT_LIST,
PANE_LIST_DATA,
onSatisfyChange() {
scatterChart.setOption(getScatterDataSet({ ...chartColors.value }));
},
onMaterialChange(value: string[]) {
const chartColors = computed(() => store.state.setting.chartColors);
lineChart.setOption(getFolderLineDataSet({ dateTime: value, ...chartColors.value }));
},
};
},
}); });
onUnmounted(() => {
window.removeEventListener('resize', updateContainer);
});
watch(
() => store.state.setting.mode,
() => {
renderCharts();
},
);
watch(
() => store.state.setting.brandTheme,
() => {
changeChartsTheme([lineChart, scatterChart]);
},
);
const onSatisfyChange = () => {
scatterChart.setOption(getScatterDataSet({ ...chartColors.value }));
};
const onMaterialChange = (value: string[]) => {
const chartColors = computed(() => store.state.setting.chartColors);
lineChart.setOption(getFolderLineDataSet({ dateTime: value, ...chartColors.value }));
};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import url('./index.less'); @import url('./index.less');

View File

@ -109,91 +109,71 @@
</t-dialog> </t-dialog>
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { prefix } from '@/config/global'; import { prefix } from '@/config/global';
import { BASE_INFO_DATA, TABLE_COLUMNS_DATA, PRODUCT_LIST } from './constants'; import { BASE_INFO_DATA, TABLE_COLUMNS_DATA as columns, PRODUCT_LIST } from './constants';
import request from '@/utils/request'; import request from '@/utils/request';
import { ResDataType } from '@/interface'; import { ResDataType } from '@/interface';
import Card from '@/components/card/index.vue'; import Card from '@/components/card/index.vue';
import Product from './components/Product.vue'; import Product from './components/Product.vue';
export default defineComponent({ const data = ref([]);
name: 'DetailAdvanced', const pagination = ref({
components: { defaultPageSize: 10,
Card, total: 100,
Product, defaultCurrent: 1,
},
setup() {
const data = ref([]);
const pagination = ref({
defaultPageSize: 10,
total: 100,
defaultCurrent: 1,
});
const updateCurrent = ref(0);
const stepUpdate = () => {
setInterval(() => {
if (updateCurrent.value > 5) {
updateCurrent.value = -1;
}
updateCurrent.value += 1;
}, 2000);
};
const fetchData = async () => {
try {
const res: ResDataType = await request.get('/api/get-purchase-list');
if (res.code === 0) {
const { list = [] } = res.data;
data.value = list;
pagination.value = {
...pagination.value,
total: list.length,
};
}
} catch (e) {
console.log(e);
}
};
onMounted(() => {
stepUpdate();
fetchData();
});
const visible = ref(false);
return {
BASE_INFO_DATA,
prefix,
PRODUCT_LIST,
columns: TABLE_COLUMNS_DATA,
data,
pagination,
visible,
updateCurrent,
sortChange(val) {
console.log(val);
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
listClick() {
visible.value = true;
},
deleteClickOp(columns) {
data.value.splice(columns.rowIndex, 1);
},
onConfirm() {
visible.value = false;
},
};
},
}); });
const updateCurrent = ref(0);
const stepUpdate = () => {
setInterval(() => {
if (updateCurrent.value > 5) {
updateCurrent.value = -1;
}
updateCurrent.value += 1;
}, 2000);
};
const fetchData = async () => {
try {
const res: ResDataType = await request.get('/api/get-purchase-list');
if (res.code === 0) {
const { list = [] } = res.data;
data.value = list;
pagination.value = {
...pagination.value,
total: list.length,
};
}
} catch (e) {
console.log(e);
}
};
onMounted(() => {
stepUpdate();
fetchData();
});
const visible = ref(false);
const sortChange = (val) => {
console.log(val);
};
const rehandleChange = (changeParams, triggerAndData) => {
console.log('统一Change', changeParams, triggerAndData);
};
const listClick = () => {
visible.value = true;
};
const deleteClickOp = (columns) => {
data.value.splice(columns.rowIndex, 1);
};
const onConfirm = () => {
visible.value = false;
};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import url('./index.less'); @import url('./index.less');

View File

@ -26,8 +26,7 @@
</card> </card>
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue';
import Card from '@/components/card/index.vue'; import Card from '@/components/card/index.vue';
const BASE_INFO_DATA = [ const BASE_INFO_DATA = [
@ -108,16 +107,6 @@ const BASE_INFO_DATA = [
type: null, type: null,
}, },
]; ];
export default defineComponent({
name: 'ListBase',
components: { Card },
data() {
return {
BASE_INFO_DATA,
};
},
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import url('./index.less'); @import url('./index.less');

View File

@ -68,8 +68,8 @@
</t-dialog> </t-dialog>
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, onMounted, onUnmounted, ref, watch, computed } from 'vue'; import { onMounted, onUnmounted, ref, watch, computed } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
@ -78,7 +78,7 @@ import { BarChart, LineChart } from 'echarts/charts';
import { CanvasRenderer } from 'echarts/renderers'; import { CanvasRenderer } from 'echarts/renderers';
import { changeChartsTheme, getSmoothLineDataSet, get2ColBarChartDataSet } from '../../dashboard/base/index'; import { changeChartsTheme, getSmoothLineDataSet, get2ColBarChartDataSet } from '../../dashboard/base/index';
import { BASE_INFO_DATA, TABLE_COLUMNS } from './constants'; import { BASE_INFO_DATA, TABLE_COLUMNS as columns } from './constants';
import { prefix } from '@/config/global'; import { prefix } from '@/config/global';
import Card from '@/components/card/index.vue'; import Card from '@/components/card/index.vue';
@ -96,118 +96,104 @@ echarts.use([
CanvasRenderer, CanvasRenderer,
]); ]);
export default defineComponent({ const store = useStore();
name: 'DetailDeploy',
components: { Card },
setup() {
const store = useStore();
const chartColors = computed(() => store.state.setting.chartColors); const chartColors = computed(() => store.state.setting.chartColors);
const data = ref([]); const data = ref([]);
const pagination = ref({ const pagination = ref({
defaultPageSize: 10, defaultPageSize: 10,
total: 100, total: 100,
defaultCurrent: 1, defaultCurrent: 1,
});
const fetchData = async () => {
try {
const res: ResDataType = await request.get('/api/get-project-list');
if (res.code === 0) {
const { list = [] } = res.data;
data.value = list;
pagination.value = {
...pagination.value,
total: list.length,
};
}
} catch (e) {
console.log(e);
}
};
const visible = ref(false);
// monitorChart logic
let monitorContainer: HTMLElement;
let monitorChart: echarts.ECharts;
onMounted(() => {
monitorContainer = document.getElementById('monitorContainer');
monitorChart = echarts.init(monitorContainer);
monitorChart.setOption(getSmoothLineDataSet({ ...chartColors.value }));
setInterval(() => {
monitorChart.setOption(getSmoothLineDataSet({ ...chartColors.value }));
}, 3000);
});
// dataChart logic
let dataContainer: HTMLElement;
let dataChart: echarts.ECharts;
onMounted(() => {
dataContainer = document.getElementById('dataContainer');
dataChart = echarts.init(dataContainer);
dataChart.setOption(get2ColBarChartDataSet({ ...chartColors.value }));
});
const intervalTimer = null;
/// / chartSize update
const updateContainer = () => {
monitorChart.resize({
width: monitorContainer.clientWidth,
height: monitorContainer.clientHeight,
});
dataChart.resize({
width: dataContainer.clientWidth,
height: dataContainer.clientHeight,
});
};
onUnmounted(() => {
window.removeEventListener('resize', updateContainer);
clearInterval(intervalTimer);
});
const onAlertChange = () => {
dataChart.setOption(get2ColBarChartDataSet({ ...chartColors.value }));
};
onMounted(() => {
fetchData();
window.addEventListener('resize', updateContainer, false);
});
watch(
() => store.state.setting.brandTheme,
() => {
changeChartsTheme([monitorChart, dataChart]);
},
);
return {
prefix,
BASE_INFO_DATA,
columns: TABLE_COLUMNS,
data,
pagination,
visible,
sortChange(val) {
console.log(val);
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
listClick() {
visible.value = true;
},
onConfirm() {
visible.value = false;
},
deleteClickOp(e) {
data.value.splice(e.rowIndex, 1);
},
onAlertChange,
};
},
}); });
const fetchData = async () => {
try {
const res: ResDataType = await request.get('/api/get-project-list');
if (res.code === 0) {
const { list = [] } = res.data;
data.value = list;
pagination.value = {
...pagination.value,
total: list.length,
};
}
} catch (e) {
console.log(e);
}
};
const visible = ref(false);
// monitorChart logic
let monitorContainer: HTMLElement;
let monitorChart: echarts.ECharts;
onMounted(() => {
monitorContainer = document.getElementById('monitorContainer');
monitorChart = echarts.init(monitorContainer);
monitorChart.setOption(getSmoothLineDataSet({ ...chartColors.value }));
setInterval(() => {
monitorChart.setOption(getSmoothLineDataSet({ ...chartColors.value }));
}, 3000);
});
// dataChart logic
let dataContainer: HTMLElement;
let dataChart: echarts.ECharts;
onMounted(() => {
dataContainer = document.getElementById('dataContainer');
dataChart = echarts.init(dataContainer);
dataChart.setOption(get2ColBarChartDataSet({ ...chartColors.value }));
});
const intervalTimer = null;
/// / chartSize update
const updateContainer = () => {
monitorChart.resize({
width: monitorContainer.clientWidth,
height: monitorContainer.clientHeight,
});
dataChart.resize({
width: dataContainer.clientWidth,
height: dataContainer.clientHeight,
});
};
onUnmounted(() => {
window.removeEventListener('resize', updateContainer);
clearInterval(intervalTimer);
});
const onAlertChange = () => {
dataChart.setOption(get2ColBarChartDataSet({ ...chartColors.value }));
};
onMounted(() => {
fetchData();
window.addEventListener('resize', updateContainer, false);
});
watch(
() => store.state.setting.brandTheme,
() => {
changeChartsTheme([monitorChart, dataChart]);
},
);
const sortChange = (val) => {
console.log(val);
};
const rehandleChange = (changeParams, triggerAndData) => {
console.log('统一Change', changeParams, triggerAndData);
};
const listClick = () => {
visible.value = true;
};
const onConfirm = () => {
visible.value = false;
};
const deleteClickOp = (e) => {
data.value.splice(e.rowIndex, 1);
};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import url('../base/index.less'); @import url('../base/index.less');

View File

@ -49,8 +49,8 @@
/> />
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref, computed, ComputedRef } from 'vue'; import { ref, computed, ComputedRef } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import { NOTIFICATION_TYPES } from '@/constants'; import { NOTIFICATION_TYPES } from '@/constants';
import { NotificationItem } from '@/interface'; import { NotificationItem } from '@/interface';
@ -71,68 +71,48 @@ const TAB_LIST = [
}, },
]; ];
export default defineComponent({ const tabValue = ref('msgData');
name: 'DetailSecondary',
components: {
EmptyIcon,
},
setup() {
const tabValue = ref('msgData');
const visible = ref(false); const visible = ref(false);
const selectedItem = ref<NotificationItem>(); const selectedItem = ref<NotificationItem>();
const store = useStore(); const store = useStore();
const { msgData } = store.state.notification; const { msgData } = store.state.notification;
const msgDataList: ComputedRef<NotificationItem[]> = computed(() => { const msgDataList: ComputedRef<NotificationItem[]> = computed(() => {
if (tabValue.value === 'msgData') return msgData; if (tabValue.value === 'msgData') return msgData;
if (tabValue.value === 'unreadMsg') return store.getters['notification/unreadMsg']; if (tabValue.value === 'unreadMsg') return store.getters['notification/unreadMsg'];
if (tabValue.value === 'readMsg') return store.getters['notification/readMsg']; if (tabValue.value === 'readMsg') return store.getters['notification/readMsg'];
return []; return [];
});
const handleClickDeleteBtn = (item: NotificationItem) => {
visible.value = true;
selectedItem.value = item;
};
const setReadStatus = (item: NotificationItem) => {
const changeMsg = msgData;
changeMsg.forEach((e: NotificationItem) => {
if (e.id === item.id) {
if (e.status) e.status = false;
}
});
store.commit('notification/setMsgData', changeMsg);
};
const deleteMsg = () => {
const item = selectedItem.value;
const changeMsg = msgData;
changeMsg.forEach((e: NotificationItem, index: number) => {
if (e.id === item?.id) {
changeMsg.splice(index, 1);
}
});
visible.value = false;
store.commit('notification/setMsgData', changeMsg);
};
return {
TAB_LIST,
NOTIFICATION_TYPES,
visible,
selectedItem,
tabValue,
msgDataList,
handleClickDeleteBtn,
setReadStatus,
deleteMsg,
};
},
}); });
const handleClickDeleteBtn = (item: NotificationItem) => {
visible.value = true;
selectedItem.value = item;
};
const setReadStatus = (item: NotificationItem) => {
const changeMsg = msgData;
changeMsg.forEach((e: NotificationItem) => {
if (e.id === item.id) {
if (e.status) e.status = false;
}
});
store.commit('notification/setMsgData', changeMsg);
};
const deleteMsg = () => {
const item = selectedItem.value;
const changeMsg = msgData;
changeMsg.forEach((e: NotificationItem, index: number) => {
if (e.id === item?.id) {
changeMsg.splice(index, 1);
}
});
visible.value = false;
store.commit('notification/setMsgData', changeMsg);
};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import url('./index.less'); @import url('./index.less');

View File

@ -154,50 +154,39 @@
</div> </div>
</t-form> </t-form>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { MessagePlugin } from 'tdesign-vue-next'; import { MessagePlugin } from 'tdesign-vue-next';
import { FORM_RULES, INITIAL_DATA, TYPE_OPTIONS, PARTY_A_OPTIONS, PARTY_B_OPTIONS } from './constants'; import { FORM_RULES, INITIAL_DATA, TYPE_OPTIONS, PARTY_A_OPTIONS, PARTY_B_OPTIONS } from './constants';
export default defineComponent({ const formData = ref({ ...INITIAL_DATA });
name: 'FormBase',
setup() { const onReset = () => {
const formData = ref({ ...INITIAL_DATA }); MessagePlugin.warning('取消新建');
return { };
TYPE_OPTIONS, const onSubmit = ({ validateResult }) => {
PARTY_A_OPTIONS, if (validateResult === true) {
PARTY_B_OPTIONS, MessagePlugin.success('新建成功');
FORM_RULES, }
formData, };
onReset() { const beforeUpload = (file) => {
MessagePlugin.warning('取消新建'); if (!/\.(pdf)$/.test(file.name)) {
}, MessagePlugin.warning('请上传pdf文件');
onSubmit({ validateResult }) { return false;
if (validateResult === true) { }
MessagePlugin.success('新建成功'); if (file.size > 60 * 1024 * 1024) {
} MessagePlugin.warning('上传文件不能大于60M');
}, return false;
beforeUpload(file) { }
if (!/\.(pdf)$/.test(file.name)) { return true;
MessagePlugin.warning('请上传pdf文件'); };
return false; const handleFail = ({ file }) => {
} MessagePlugin.error(`文件 ${file.name} 上传失败`);
if (file.size > 60 * 1024 * 1024) { };
MessagePlugin.warning('上传文件不能大于60M'); // error url /
return false; const formatResponse = (res) => {
} return { ...res, error: '上传失败,请重试', url: res.url };
return true; };
},
handleFail({ file }) {
MessagePlugin.error(`文件 ${file.name} 上传失败`);
},
// error url /
formatResponse(res) {
return { ...res, error: '上传失败,请重试', url: res.url };
},
};
},
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import url('./index.less'); @import url('./index.less');

View File

@ -139,8 +139,8 @@
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref, computed } from 'vue'; import { ref, computed } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { ValidateResultContext } from 'tdesign-vue-next'; import { ValidateResultContext } from 'tdesign-vue-next';
import Card from '@/components/card/index.vue'; import Card from '@/components/card/index.vue';
@ -155,53 +155,36 @@ import {
INITIAL_DATA3, INITIAL_DATA3,
} from './constants'; } from './constants';
export default defineComponent({ const formData1 = ref({ ...INITIAL_DATA1 });
name: 'FormStep', const formData2 = ref({ ...INITIAL_DATA2 });
components: { Card }, const formData3 = ref({ ...INITIAL_DATA3 });
setup() { const activeForm = ref(0);
const formData1 = ref({ ...INITIAL_DATA1 });
const formData2 = ref({ ...INITIAL_DATA2 });
const formData3 = ref({ ...INITIAL_DATA3 });
const activeForm = ref(0);
const amount = computed(() => { const amount = computed(() => {
if (formData1.value.name === '1') { if (formData1.value.name === '1') {
return '565421'; return '565421';
} }
if (formData1.value.name === '2') { if (formData1.value.name === '2') {
return '278821'; return '278821';
} }
if (formData1.value.name === '3') { if (formData1.value.name === '3') {
return '109824'; return '109824';
} }
return '--'; return '--';
});
return {
NAME_OPTIONS,
TYPE_OPTIONS,
ADDRESS_OPTIONS,
FORM_RULES,
formData1,
formData2,
formData3,
activeForm,
amount,
onSubmit(result: ValidateResultContext<FormData>, val: number) {
if (result.validateResult === true) {
activeForm.value = val;
}
},
onReset(val: number) {
activeForm.value = val;
},
complete() {
const router = useRouter();
router.replace({ path: '/detail/advanced' });
},
};
},
}); });
const onSubmit = (result: ValidateResultContext<FormData>, val: number) => {
if (result.validateResult === true) {
activeForm.value = val;
}
};
const onReset = (val: number) => {
activeForm.value = val;
};
const complete = () => {
const router = useRouter();
router.replace({ path: '/detail/advanced' });
};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import url('./index.less'); @import url('./index.less');

View File

@ -64,8 +64,8 @@
/> />
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref, onMounted, computed } from 'vue'; import { ref, onMounted, computed } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { SearchIcon } from 'tdesign-icons-vue-next'; import { SearchIcon } from 'tdesign-icons-vue-next';
import { MessagePlugin } from 'tdesign-vue-next'; import { MessagePlugin } from 'tdesign-vue-next';
@ -78,121 +78,96 @@ import request from '@/utils/request';
import { COLUMNS } from './constants'; import { COLUMNS } from './constants';
export default defineComponent({ const data = ref([]);
name: 'ListBaseCard', const pagination = ref({
components: { defaultPageSize: 20,
Card, total: 100,
SearchIcon, defaultCurrent: 1,
Trend,
},
setup() {
const data = ref([]);
const pagination = ref({
defaultPageSize: 20,
total: 100,
defaultCurrent: 1,
});
const searchValue = ref('');
const dataLoading = ref(false);
const fetchData = async () => {
dataLoading.value = true;
try {
const res: ResDataType = await request.get('/api/get-list');
if (res.code === 0) {
const { list = [] } = res.data;
data.value = list;
pagination.value = {
...pagination.value,
total: list.length,
};
}
} catch (e) {
console.log(e);
} finally {
dataLoading.value = false;
}
};
const deleteIdx = ref(-1);
const confirmBody = computed(() => {
if (deleteIdx.value > -1) {
const { name } = data.value[deleteIdx.value];
return `删除后,${name}的所有合同信息将被清空,且无法恢复`;
}
return '';
});
onMounted(() => {
fetchData();
});
const confirmVisible = ref(false);
const selectedRowKeys = ref([1, 2]);
const router = useRouter();
const resetIdx = () => {
deleteIdx.value = -1;
};
const onConfirmDelete = () => {
//
data.value.splice(deleteIdx.value, 1);
pagination.value.total = data.value.length;
const selectedIdx = selectedRowKeys.value.indexOf(deleteIdx.value);
if (selectedIdx > -1) {
selectedRowKeys.value.splice(selectedIdx, 1);
}
confirmVisible.value = false;
MessagePlugin.success('删除成功');
resetIdx();
};
const onCancel = () => {
resetIdx();
};
return {
CONTRACT_STATUS,
CONTRACT_TYPES,
CONTRACT_PAYMENT_TYPES,
COLUMNS,
data,
searchValue,
dataLoading,
pagination,
confirmBody,
confirmVisible,
rowKey: 'index',
onConfirmDelete,
onCancel,
selectedRowKeys,
rehandleSelectChange(val: number[]) {
selectedRowKeys.value = val;
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
handleClickDetail() {
router.push('/detail/base');
},
handleSetupContract() {
router.push('/form/base');
},
handleClickDelete(row: { rowIndex: any }) {
deleteIdx.value = row.rowIndex;
confirmVisible.value = true;
},
};
},
methods: {},
}); });
const searchValue = ref('');
const dataLoading = ref(false);
const fetchData = async () => {
dataLoading.value = true;
try {
const res: ResDataType = await request.get('/api/get-list');
if (res.code === 0) {
const { list = [] } = res.data;
data.value = list;
pagination.value = {
...pagination.value,
total: list.length,
};
}
} catch (e) {
console.log(e);
} finally {
dataLoading.value = false;
}
};
const deleteIdx = ref(-1);
const confirmBody = computed(() => {
if (deleteIdx.value > -1) {
const { name } = data.value[deleteIdx.value];
return `删除后,${name}的所有合同信息将被清空,且无法恢复`;
}
return '';
});
onMounted(() => {
fetchData();
});
const confirmVisible = ref(false);
const selectedRowKeys = ref([1, 2]);
const router = useRouter();
const resetIdx = () => {
deleteIdx.value = -1;
};
const onConfirmDelete = () => {
//
data.value.splice(deleteIdx.value, 1);
pagination.value.total = data.value.length;
const selectedIdx = selectedRowKeys.value.indexOf(deleteIdx.value);
if (selectedIdx > -1) {
selectedRowKeys.value.splice(selectedIdx, 1);
}
confirmVisible.value = false;
MessagePlugin.success('删除成功');
resetIdx();
};
const onCancel = () => {
resetIdx();
};
const rowKey = 'index';
const rehandleSelectChange = (val: number[]) => {
selectedRowKeys.value = val;
};
const rehandlePageChange = (curr, pageInfo) => {
console.log('分页变化', curr, pageInfo);
};
const rehandleChange = (changeParams, triggerAndData) => {
console.log('统一Change', changeParams, triggerAndData);
};
const handleClickDetail = () => {
router.push('/detail/base');
};
const handleSetupContract = () => {
router.push('/form/base');
};
const handleClickDelete = (row: { rowIndex: any }) => {
deleteIdx.value = row.rowIndex;
confirmVisible.value = true;
};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables'; @import '@/style/variables';

View File

@ -8,8 +8,8 @@
</t-form-item> </t-form-item>
<t-form-item label="产品状态" name="status"> <t-form-item label="产品状态" name="status">
<t-radio-group v-model="formData.status"> <t-radio-group v-model="formData.status">
<t-radio value="0"> 已停用 </t-radio> <t-radio value="0">已停用</t-radio>
<t-radio value="1"> 已启用 </t-radio> <t-radio value="1">已启用</t-radio>
</t-radio-group> </t-radio-group>
</t-form-item> </t-form-item>
<t-form-item label="产品描述" name="description"> <t-form-item label="产品描述" name="description">
@ -26,16 +26,16 @@
<t-textarea v-model="textareaValue" :style="{ width: '480px' }" placeholder="请输入内容" name="description" /> <t-textarea v-model="textareaValue" :style="{ width: '480px' }" placeholder="请输入内容" name="description" />
</t-form-item> </t-form-item>
<t-form-item style="float: right"> <t-form-item style="float: right">
<t-button variant="outline" @click="onClickCloseBtn"> 取消 </t-button> <t-button variant="outline" @click="onClickCloseBtn">取消</t-button>
<t-button theme="primary" type="submit"> 确定 </t-button> <t-button theme="primary" type="submit">确定</t-button>
</t-form-item> </t-form-item>
</t-form> </t-form>
</template> </template>
</t-dialog> </t-dialog>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { MessagePlugin } from 'tdesign-vue-next'; import { MessagePlugin } from 'tdesign-vue-next';
const INITIAL_DATA = { const INITIAL_DATA = {
@ -53,72 +53,61 @@ const SELECT_OPTIONS = [
{ label: 'CVM', value: '3' }, { label: 'CVM', value: '3' },
]; ];
export default defineComponent({ const props = defineProps({
props: { visible: {
visible: { type: Boolean,
type: Boolean, default: false,
default: false,
},
data: {
type: Object,
default: () => {
return {};
},
},
}, },
setup(props, ctx) { data: {
const formVisible = ref(false); type: Object,
const formData = ref(props.data); default: () => {
const textareaValue = ref(''); return {};
},
const onSubmit = ({ result, firstError }) => {
if (!firstError) {
MessagePlugin.success('提交成功');
formVisible.value = false;
} else {
console.log('Errors: ', result);
MessagePlugin.warning(firstError);
}
};
const onClickCloseBtn = () => {
formVisible.value = false;
formData.value = { ...INITIAL_DATA };
};
watch(
() => formVisible.value,
(val) => {
const { emit } = ctx;
emit('update:visible', val);
},
);
watch(
() => props.visible,
(val) => {
formVisible.value = val;
},
);
watch(
() => props.data,
(val) => {
formData.value = val;
},
);
return {
SELECT_OPTIONS,
formVisible,
formData,
textareaValue,
onSubmit,
onClickCloseBtn,
rules: {
name: [{ required: true, message: '请输入产品名称', type: 'error' }],
},
};
}, },
}); });
const formVisible = ref(false);
const formData = ref(props.data);
const textareaValue = ref('');
const onSubmit = ({ result, firstError }) => {
if (!firstError) {
MessagePlugin.success('提交成功');
formVisible.value = false;
} else {
console.log('Errors: ', result);
MessagePlugin.warning(firstError);
}
};
const onClickCloseBtn = () => {
formVisible.value = false;
formData.value = { ...INITIAL_DATA };
};
const emit = defineEmits(['update:visible']);
watch(
() => formVisible.value,
(val) => {
emit('update:visible', val);
},
);
watch(
() => props.visible,
(val) => {
formVisible.value = val;
},
);
watch(
() => props.data,
(val) => {
formData.value = val;
},
);
const rules = {
name: [{ required: true, message: '请输入产品名称', type: 'error' }],
};
</script> </script>

View File

@ -58,8 +58,8 @@
/> />
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref, computed, onMounted } from 'vue'; import { ref, computed, onMounted } from 'vue';
import { SearchIcon } from 'tdesign-icons-vue-next'; import { SearchIcon } from 'tdesign-icons-vue-next';
import { MessagePlugin } from 'tdesign-vue-next'; import { MessagePlugin } from 'tdesign-vue-next';
import Card from '@/components/card/Card.vue'; import Card from '@/components/card/Card.vue';
@ -76,88 +76,68 @@ const INITIAL_DATA = {
amount: 0, amount: 0,
}; };
export default defineComponent({ const pagination = ref({ current: 1, pageSize: 12, total: 0 });
name: 'ListBase', const deleteProduct = ref(undefined);
components: {
SearchIcon,
Card,
DialogForm,
},
setup() {
const pagination = ref({ current: 1, pageSize: 12, total: 0 });
const deleteProduct = ref(undefined);
const productList = ref([]); const productList = ref([]);
const dataLoading = ref(true); const dataLoading = ref(true);
const fetchData = async () => { const fetchData = async () => {
try { try {
const res: ResDataType = await request.get('/api/get-card-list'); const res: ResDataType = await request.get('/api/get-card-list');
if (res.code === 0) { if (res.code === 0) {
const { list = [] } = res.data; const { list = [] } = res.data;
productList.value = list; productList.value = list;
pagination.value = { pagination.value = {
...pagination.value, ...pagination.value,
total: list.length, total: list.length,
}; };
} }
} catch (e) { } catch (e) {
console.log(e); console.log(e);
} finally { } finally {
dataLoading.value = false; dataLoading.value = false;
} }
}; };
const confirmBody = computed(() => const confirmBody = computed(() =>
deleteProduct.value ? `确认删除后${deleteProduct.value.name}的所有产品信息将被清空, 且无法恢复` : '', deleteProduct.value ? `确认删除后${deleteProduct.value.name}的所有产品信息将被清空, 且无法恢复` : '',
); );
onMounted(() => { onMounted(() => {
fetchData(); fetchData();
});
const formDialogVisible = ref(false);
const searchValue = ref('');
const confirmVisible = ref(false);
const formData = ref({ ...INITIAL_DATA });
return {
pagination,
productList,
dataLoading,
formDialogVisible,
confirmBody,
searchValue,
confirmVisible,
formData,
onPageSizeChange(size: number) {
pagination.value.pageSize = size;
pagination.value.current = 1;
},
onCurrentChange(current: number) {
pagination.value.current = current;
},
handleDeleteItem(product) {
confirmVisible.value = true;
deleteProduct.value = product;
},
onConfirmDelete() {
const { index } = deleteProduct.value;
productList.value.splice(index - 1, 1);
confirmVisible.value = false;
MessagePlugin.success('删除成功');
},
onCancel() {
deleteProduct.value = undefined;
formData.value = { ...INITIAL_DATA };
},
handleManageProduct(product) {
formDialogVisible.value = true;
formData.value = { ...product, status: product?.isSetup ? '1' : '0' };
},
};
},
}); });
const formDialogVisible = ref(false);
const searchValue = ref('');
const confirmVisible = ref(false);
const formData = ref({ ...INITIAL_DATA });
const onPageSizeChange = (size: number) => {
pagination.value.pageSize = size;
pagination.value.current = 1;
};
const onCurrentChange = (current: number) => {
pagination.value.current = current;
};
const handleDeleteItem = (product) => {
confirmVisible.value = true;
deleteProduct.value = product;
};
const onConfirmDelete = () => {
const { index } = deleteProduct.value;
productList.value.splice(index - 1, 1);
confirmVisible.value = false;
MessagePlugin.success('删除成功');
};
const onCancel = () => {
deleteProduct.value = undefined;
formData.value = { ...INITIAL_DATA };
};
const handleManageProduct = (product) => {
formDialogVisible.value = true;
formData.value = { ...product, status: product?.isSetup ? '1' : '0' };
};
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less'; @import '@/style/variables.less';

View File

@ -102,8 +102,8 @@
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref, computed, onMounted } from 'vue'; import { ref, computed, onMounted } from 'vue';
import { MessagePlugin } from 'tdesign-vue-next'; import { MessagePlugin } from 'tdesign-vue-next';
import Trend from '@/components/trend/index.vue'; import Trend from '@/components/trend/index.vue';
import request from '@/utils/request'; import request from '@/utils/request';
@ -167,115 +167,89 @@ const searchForm = {
type: '', type: '',
}; };
export default defineComponent({ const formData = ref({ ...searchForm });
name: 'ListTable', const rowKey = 'index';
components: { const verticalAlign = 'top';
Trend, const hover = true;
},
setup() {
const formData = ref({ ...searchForm });
const tableConfig = {
rowKey: 'index',
verticalAlign: 'top',
hover: true,
};
const pagination = ref({
defaultPageSize: 20,
total: 100,
defaultCurrent: 1,
});
const confirmVisible = ref(false);
const data = ref([]); const pagination = ref({
defaultPageSize: 20,
const dataLoading = ref(false); total: 100,
const fetchData = async () => { defaultCurrent: 1,
dataLoading.value = true;
try {
const res: ResDataType = await request.get('/api/get-list');
if (res.code === 0) {
const { list = [] } = res.data;
data.value = list;
pagination.value = {
...pagination.value,
total: list.length,
};
}
} catch (e) {
console.log(e);
} finally {
dataLoading.value = false;
}
};
const deleteIdx = ref(-1);
const confirmBody = computed(() => {
if (deleteIdx.value > -1) {
const { name } = data.value[deleteIdx.value];
return `删除后,${name}的所有合同信息将被清空,且无法恢复`;
}
return '';
});
const resetIdx = () => {
deleteIdx.value = -1;
};
const onConfirmDelete = () => {
//
data.value.splice(deleteIdx.value, 1);
pagination.value.total = data.value.length;
confirmVisible.value = false;
MessagePlugin.success('删除成功');
resetIdx();
};
const onCancel = () => {
resetIdx();
};
onMounted(() => {
fetchData();
});
return {
data,
COLUMNS,
CONTRACT_STATUS,
CONTRACT_STATUS_OPTIONS,
CONTRACT_TYPES,
CONTRACT_TYPE_OPTIONS,
CONTRACT_PAYMENT_TYPES,
formData,
pagination,
confirmVisible,
confirmBody,
...tableConfig,
onConfirmDelete,
onCancel,
dataLoading,
handleClickDelete({ row }) {
deleteIdx.value = row.rowIndex;
confirmVisible.value = true;
},
onReset(val) {
console.log(val);
},
onSubmit(val) {
console.log(val);
},
rehandlePageChange(curr, pageInfo) {
console.log('分页变化', curr, pageInfo);
},
rehandleChange(changeParams, triggerAndData) {
console.log('统一Change', changeParams, triggerAndData);
},
rehandleClickOp({ text, row }) {
console.log(text, row);
},
};
},
}); });
const confirmVisible = ref(false);
const data = ref([]);
const dataLoading = ref(false);
const fetchData = async () => {
dataLoading.value = true;
try {
const res: ResDataType = await request.get('/api/get-list');
if (res.code === 0) {
const { list = [] } = res.data;
data.value = list;
pagination.value = {
...pagination.value,
total: list.length,
};
}
} catch (e) {
console.log(e);
} finally {
dataLoading.value = false;
}
};
const deleteIdx = ref(-1);
const confirmBody = computed(() => {
if (deleteIdx.value > -1) {
const { name } = data.value[deleteIdx.value];
return `删除后,${name}的所有合同信息将被清空,且无法恢复`;
}
return '';
});
const resetIdx = () => {
deleteIdx.value = -1;
};
const onConfirmDelete = () => {
//
data.value.splice(deleteIdx.value, 1);
pagination.value.total = data.value.length;
confirmVisible.value = false;
MessagePlugin.success('删除成功');
resetIdx();
};
const onCancel = () => {
resetIdx();
};
onMounted(() => {
fetchData();
});
const handleClickDelete = ({ row }) => {
deleteIdx.value = row.rowIndex;
confirmVisible.value = true;
};
const onReset = (val) => {
console.log(val);
};
const onSubmit = (val) => {
console.log(val);
};
const rehandlePageChange = (curr, pageInfo) => {
console.log('分页变化', curr, pageInfo);
};
const rehandleChange = (changeParams, triggerAndData) => {
console.log('统一Change', changeParams, triggerAndData);
};
const rehandleClickOp = ({ text, row }) => {
console.log(text, row);
};
</script> </script>
<style lang="less"> <style lang="less">

View File

@ -1,14 +1,6 @@
<template> <template>
<common-table /> <common-table />
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue';
import CommonTable from '../components/CommonTable.vue'; import CommonTable from '../components/CommonTable.vue';
export default defineComponent({
name: 'ListBase',
components: {
CommonTable,
},
});
</script> </script>

View File

@ -15,38 +15,24 @@
</div> </div>
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { SearchIcon } from 'tdesign-icons-vue-next'; import { SearchIcon } from 'tdesign-icons-vue-next';
import { prefix } from '@/config/global';
import { TREE_DATA } from './constants'; import { TREE_DATA } from './constants';
import CommonTable from '../components/CommonTable.vue'; import CommonTable from '../components/CommonTable.vue';
export default defineComponent({ const filterByText = ref();
name: 'ListTree', const filterText = ref();
components: {
SearchIcon, const expanded = ['0', '0-0', '0-1', '0-2', '0-3', '0-4'];
CommonTable,
}, const onInput = () => {
setup() { filterByText.value = (node) => {
const filterByText = ref(); const rs = node.label.indexOf(filterText.value) >= 0;
const filterText = ref(); return rs;
return { };
prefix, };
TREE_DATA,
expanded: ['0', '0-0', '0-1', '0-2', '0-3', '0-4'],
filterText,
filterByText,
onInput() {
filterByText.value = (node) => {
const rs = node.label.indexOf(filterText.value) >= 0;
return rs;
};
},
};
},
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less'; @import '@/style/variables.less';

View File

@ -15,34 +15,22 @@
</header> </header>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import LogoFullIcon from '@/assets/assets-logo-full.svg?component'; import LogoFullIcon from '@/assets/assets-logo-full.svg?component';
export default defineComponent({ const store = useStore();
components: { LogoFullIcon }, const toggleSettingPanel = () => {
setup() { store.commit('setting/toggleSettingPanel', true);
const store = useStore(); };
const toggleSettingPanel = () => {
store.commit('setting/toggleSettingPanel', true);
};
const navToGitHub = () => { const navToGitHub = () => {
window.open('https://github.com/tencent/tdesign-vue-next-starter'); window.open('https://github.com/tencent/tdesign-vue-next-starter');
}; };
const navToHelper = () => { const navToHelper = () => {
window.open('http://tdesign.tencent.com/starter/docs/get-started'); window.open('http://tdesign.tencent.com/starter/docs/get-started');
}; };
return {
toggleSettingPanel,
navToGitHub,
navToHelper,
};
},
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>

View File

@ -70,8 +70,8 @@
</t-form> </t-form>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import QrcodeVue from 'qrcode.vue'; import QrcodeVue from 'qrcode.vue';
@ -93,48 +93,32 @@ const FORM_RULES = {
verifyCode: [{ required: true, message: '验证码必填', type: 'error' }], verifyCode: [{ required: true, message: '验证码必填', type: 'error' }],
}; };
export default defineComponent({ const type = ref('password');
components: { QrcodeVue },
setup() {
const type = ref('password');
const formData = ref({ ...INITIAL_DATA }); const formData = ref({ ...INITIAL_DATA });
const showPsw = ref(false); const showPsw = ref(false);
const [countDown, handleCounter] = useCounter(); const [countDown, handleCounter] = useCounter();
const switchType = (val: string) => { const switchType = (val: string) => {
type.value = val; type.value = val;
}; };
const router = useRouter(); const router = useRouter();
const store = useStore(); const store = useStore();
const onSubmit = async ({ validateResult }) => { const onSubmit = async ({ validateResult }) => {
if (validateResult === true) { if (validateResult === true) {
try { try {
await store.dispatch('user/login', formData.value); await store.dispatch('user/login', formData.value);
MessagePlugin.success('登陆成功'); MessagePlugin.success('登陆成功');
router.push({ router.push({
path: '/dashboard/base', path: '/dashboard/base',
}); });
} catch (e) { } catch (e) {
console.log(e); console.log(e);
MessagePlugin.error(e.message); MessagePlugin.error(e.message);
} }
} }
}; };
return {
FORM_RULES,
formData,
showPsw,
type,
switchType,
countDown,
handleCounter,
onSubmit,
};
},
});
</script> </script>

View File

@ -70,8 +70,8 @@
</t-form> </t-form>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import { MessagePlugin } from 'tdesign-vue-next'; import { MessagePlugin } from 'tdesign-vue-next';
import { useCounter } from '@/hooks'; import { useCounter } from '@/hooks';
@ -93,47 +93,30 @@ const FORM_RULES = {
verifyCode: [{ required: true, message: '验证码必填', type: 'error' }], verifyCode: [{ required: true, message: '验证码必填', type: 'error' }],
}; };
export default defineComponent({ const type = ref('phone');
setup(props, ctx) {
const type = ref('phone');
const emailOptions = ref([]);
const form = ref(); const form = ref();
const formData = ref({ ...INITIAL_DATA }); const formData = ref({ ...INITIAL_DATA });
const showPsw = ref(false); const showPsw = ref(false);
const [countDown, handleCounter] = useCounter(); const [countDown, handleCounter] = useCounter();
const onSubmit = ({ validateResult }) => { const emit = defineEmits(['registerSuccess']);
if (validateResult === true) {
if (!formData.value.checked) {
MessagePlugin.error('请同意TDesign服务协议和TDesign 隐私声明');
return;
}
MessagePlugin.success('注册成功');
const { emit } = ctx;
emit('registerSuccess');
}
};
const switchType = (val) => { const onSubmit = ({ validateResult }) => {
form.value.reset(); if (validateResult === true) {
type.value = val; if (!formData.value.checked) {
}; MessagePlugin.error('请同意TDesign服务协议和TDesign 隐私声明');
return;
}
MessagePlugin.success('注册成功');
emit('registerSuccess');
}
};
return { const switchType = (val) => {
FORM_RULES, form.value.reset();
formData, type.value = val;
showPsw, };
form,
type,
emailOptions,
countDown,
handleCounter,
onSubmit,
switchType,
};
},
});
</script> </script>

View File

@ -22,34 +22,18 @@
<footer class="copyright">Copyright @ 2021-2022 Tencent. All Rights Reserved</footer> <footer class="copyright">Copyright @ 2021-2022 Tencent. All Rights Reserved</footer>
</div> </div>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, ref } from 'vue'; import { ref } from 'vue';
import Login from './components/Login.vue'; import Login from './components/Login.vue';
import Register from './components/Register.vue'; import Register from './components/Register.vue';
import LoginHeader from './components/Header.vue'; import LoginHeader from './components/Header.vue';
import TdesignSetting from '@/layouts/setting.vue'; import TdesignSetting from '@/layouts/setting.vue';
export default defineComponent({ const type = ref('login');
name: 'LoginIndex', const switchType = (val: string) => {
components: { type.value = val;
Login, };
Register,
LoginHeader,
TdesignSetting,
},
setup() {
const type = ref('login');
const switchType = (val: string) => {
type.value = val;
};
return {
type,
switchType,
};
},
});
</script> </script>
<style lang="less"> <style lang="less">
@import url('./index.less'); @import url('./index.less');

View File

@ -4,12 +4,6 @@
</result> </result>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue';
import Result from '@/components/result/index.vue'; import Result from '@/components/result/index.vue';
export default defineComponent({
name: 'Result403',
components: { Result },
});
</script> </script>

View File

@ -4,12 +4,6 @@
</result> </result>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue';
import Result from '@/components/result/index.vue'; import Result from '@/components/result/index.vue';
export default defineComponent({
name: 'Result404',
components: { Result },
});
</script> </script>

View File

@ -4,12 +4,6 @@
</result> </result>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue';
import Result from '@/components/result/index.vue'; import Result from '@/components/result/index.vue';
export default defineComponent({
name: 'Result500',
components: { Result },
});
</script> </script>

View File

@ -19,15 +19,9 @@
</result> </result>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue';
import Result from '@/components/result/index.vue'; import Result from '@/components/result/index.vue';
import Thumbnail from '@/components/thumbnail/index.vue'; import Thumbnail from '@/components/thumbnail/index.vue';
export default defineComponent({
name: 'ResultBrowserIncompatible',
components: { Result, Thumbnail },
});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less'; @import '@/style/variables.less';

View File

@ -10,14 +10,6 @@
</div> </div>
</template> </template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'ResultSuccess',
});
</script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less'; @import '@/style/variables.less';

View File

@ -7,12 +7,6 @@
</result> </result>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent } from 'vue';
import Result from '@/components/result/index.vue'; import Result from '@/components/result/index.vue';
export default defineComponent({
name: 'ResultNetworkError',
components: { Result },
});
</script> </script>

View File

@ -10,14 +10,6 @@
</div> </div>
</template> </template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'ResultSuccess',
});
</script>
<style lang="less" scoped> <style lang="less" scoped>
@import '@/style/variables.less'; @import '@/style/variables.less';

View File

@ -89,8 +89,8 @@
</t-col> </t-col>
</t-row> </t-row>
</template> </template>
<script lang="ts"> <script setup lang="ts">
import { defineComponent, nextTick, onMounted, onUnmounted, watch, computed } from 'vue'; import { nextTick, onMounted, onUnmounted, watch, computed } from 'vue';
import { useStore } from 'vuex'; import { useStore } from 'vuex';
import * as echarts from 'echarts/core'; import * as echarts from 'echarts/core';
import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components'; import { GridComponent, TooltipComponent, LegendComponent } from 'echarts/components';
@ -109,84 +109,68 @@ import Card from '@/components/card/index.vue';
echarts.use([GridComponent, TooltipComponent, LineChart, CanvasRenderer, LegendComponent]); echarts.use([GridComponent, TooltipComponent, LineChart, CanvasRenderer, LegendComponent]);
export default defineComponent({ let lineContainer: HTMLElement;
components: { let lineChart: echarts.ECharts;
Card, const store = useStore();
}, const chartColors = computed(() => store.state.setting.chartColors);
setup() {
let lineContainer: HTMLElement;
let lineChart: echarts.ECharts;
const store = useStore();
const chartColors = computed(() => store.state.setting.chartColors);
const onLineChange = (value) => { const onLineChange = (value) => {
lineChart.setOption(getFolderLineDataSet(value)); lineChart.setOption(getFolderLineDataSet(value));
}; };
const initChart = () => { const initChart = () => {
lineContainer = document.getElementById('lineContainer'); lineContainer = document.getElementById('lineContainer');
lineChart = echarts.init(lineContainer); lineChart = echarts.init(lineContainer);
lineChart.setOption({ lineChart.setOption({
grid: { grid: {
x: 30, // 80px x: 30, // 80px
y: 30, // 60px y: 30, // 60px
x2: 10, // 80px x2: 10, // 80px
y2: 30, // 60px y2: 30, // 60px
}, },
...getFolderLineDataSet({ ...chartColors.value }), ...getFolderLineDataSet({ ...chartColors.value }),
}); });
}; };
const updateContainer = () => { const updateContainer = () => {
lineChart?.resize({ lineChart?.resize({
width: lineContainer.clientWidth, width: lineContainer.clientWidth,
height: lineContainer.clientHeight, height: lineContainer.clientHeight,
}); });
}; };
onMounted(() => { onMounted(() => {
nextTick(() => { nextTick(() => {
initChart(); initChart();
}); });
window.addEventListener('resize', updateContainer, false); window.addEventListener('resize', updateContainer, false);
});
onUnmounted(() => {
window.removeEventListener('resize', updateContainer);
});
const getIcon = (type) => {
switch (type) {
case 'a':
return ProductAIcon;
case 'b':
return ProductBIcon;
case 'c':
return ProductCIcon;
case 'd':
return ProductDIcon;
default:
return ProductAIcon;
}
};
watch(
() => store.state.setting.brandTheme,
() => {
changeChartsTheme([lineChart]);
},
);
return {
LAST_7_DAYS,
USER_INFO_LIST,
TEAM_MEMBERS,
PRODUCT_LIST,
onLineChange,
getIcon,
};
},
}); });
onUnmounted(() => {
window.removeEventListener('resize', updateContainer);
});
const getIcon = (type) => {
switch (type) {
case 'a':
return ProductAIcon;
case 'b':
return ProductBIcon;
case 'c':
return ProductCIcon;
case 'd':
return ProductDIcon;
default:
return ProductAIcon;
}
};
watch(
() => store.state.setting.brandTheme,
() => {
changeChartsTheme([lineChart]);
},
);
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
@import url('./index.less'); @import url('./index.less');