提交 35e0c1cd 编写于 作者: Z zhaoke

* Finish task 54833

上级 994d5743
<template>
<ZModal
:showModal="showModalRef"
@onCancel="cancel"
@onOk="submit"
:title="t('pls_name')"
>
<Form class="form-site" labelCol="6" wrapperCol="16">
<FormItem name="name" :label="t('name')" :info="validateInfos.name">
<input v-model="modelRef.name" class="form-control" />
</FormItem>
<FormItem name="url" :label="t('zentao_url')" :info="validateInfos.url">
<input v-model="modelRef.url" class="form-control" />
</FormItem>
<FormItem
name="username"
:label="t('username')"
:info="validateInfos.username"
>
<input v-model="modelRef.username" class="form-control" />
</FormItem>
<FormItem
name="password"
:label="t('password')"
:info="validateInfos.password"
>
<input v-model="modelRef.password" class="form-control" />
</FormItem>
</Form>
</ZModal>
</template>
<script setup lang="ts">
import { useI18n } from "vue-i18n";
import { useStore } from "vuex";
import { ZentaoData } from "@/store/zentao";
import { ScriptData } from "@/views/script/store";
import { unitTestTypesDef, ztfTestTypesDef } from "@/utils/const";
import {
computed,
defineExpose,
onMounted,
withDefaults,
ref,
defineProps,
defineEmits,
watch,
} from "vue";
import { useForm } from "@/utils/form";
import Form from "./Form.vue";
import FormItem from "./FormItem.vue";
import { StateType } from "@/views/site/store";
export interface FormSiteProps {
show?: boolean;
id?: number;
}
const { t } = useI18n();
const props = withDefaults(defineProps<FormSiteProps>(), {
show: false,
id: 0
});
const showModalRef = computed(() => {
return props.show;
});
const store = useStore<{ Site: StateType }>();
const get = async (id: number): Promise<void> => {
await store.dispatch("Site/get", id);
};
watch(props, () => {
get(props.id);
})
get(props.id);
const cancel = () => {
emit("cancel", {});
};
const modelRef = computed(() => store.state.Site.detailResult);
const rulesRef = ref({
name: [{ required: true, msg: t("pls_name") }],
url: [
{
required: true,
msg: t("pls_zentao_url"),
},
{
regex:
/(http?|https):\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/i,
msg: t("pls_zentao_url"),
},
],
username: [{ required: true, msg: t("pls_username") }],
password: [{ required: true, msg: t("pls_password") }],
});
const { validate, reset, validateInfos } = useForm(modelRef, rulesRef);
const emit = defineEmits<{
(type: "submit", event: {}): void;
(type: "cancel", event: {}): void;
}>();
const submit = () => {
if (validate()) {
console.log("submit", validate());
emit("submit", modelRef.value);
}
};
const clearFormData = () => {
modelRef.value = {};
};
defineExpose({
clearFormData,
});
</script>
<style lang="less" scoped>
.workdir {
height: calc(100vh - 80px);
}
.form-control {
width: 100%;
color: #495057;
background-color: #fff;
border: 1px solid #ced4da;
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
.z-form-item-label {
font-weight: 400;
color: #212529;
text-align: left;
box-sizing: border-box;
display: inline-block;
position: relative;
width: 100%;
padding-right: 15px;
padding-left: 15px;
padding-top: calc(0.375rem + 1px);
padding-bottom: calc(0.375rem + 1px);
margin-bottom: 0;
line-height: 1.5;
}
.z-form-item {
display: flex;
align-items: center;
}
.form-control:focus {
color: #495057;
background-color: #fff;
border-color: #80bdff;
outline: 0;
box-shadow: 0 0 0 0.2rem rgb(0 123 255 / 25%);
}
.form-site {
min-width: 500px;
}
</style>
\ No newline at end of file
......@@ -128,8 +128,6 @@ defineExpose({
width: 100%;
padding-right: 15px;
padding-left: 15px;
flex: 0 0 16.666667%;
max-width: 16.666667%;
padding-top: calc(0.375rem + 1px);
padding-bottom: calc(0.375rem + 1px);
margin-bottom: 0;
......
......@@ -52,12 +52,8 @@ import { $vfm } from "vue-final-modal";
export interface ZModalProps {
showModal?: boolean;
title: string;
onCancel?: {
type: Function;
};
onOk?: {
type: Function;
};
onCancel?: Function;
onOk?: Function;
okTitle?: string;
cancelTitle?: string;
content?: string;
......@@ -92,7 +88,7 @@ const confirm = (params) => {
const onCancel = () => {
if (props.isConfirm) {
$vfm.hide("ZModal");
if (props.onOk && typeof props.onOk === "function") {
if (props.onCancel && typeof props.onCancel === "function") {
props.onCancel();
}
}
......
......@@ -35,6 +35,12 @@
:replaceFields="replaceFields"
/>
<FormSite
:show="showCreateSiteModal"
@submit="createSite"
@cancel="modalClose"
ref="formSite"
/>
</template>
<script setup lang="ts">
......@@ -45,9 +51,10 @@ import {useI18n} from "vue-i18n";
import {useRouter} from "vue-router";
import {useStore} from "vuex";
import {ZentaoData} from "@/store/zentao";
import {computed, onMounted, watch} from "vue";
import {computed, onMounted, watch, ref} from "vue";
import {getInitStatus} from "@/utils/cache";
import {notification} from "ant-design-vue";
import FormSite from "./FormSite.vue";
const { t } = useI18n();
const router = useRouter();
......@@ -94,13 +101,7 @@ const showZentaoMsg = (payload): void => {
const selectSite = (item): void => {
console.log('selectSite', item.key)
if(item.key == -1){
// create site
// store.dispatch('tabs/open', {
// id: 'createSite',
// title: t('createSite'),
// type: 'settings',
// data: {action:'createSite'}
// });
showCreateSiteModal.value = true;
}
store.dispatch('Zentao/fetchSitesAndProduct', {currSiteId: item.key}).then((payload) => {
showZentaoMsg(payload)
......@@ -118,6 +119,20 @@ const replaceFields = {
title: 'name',
}
const showCreateSiteModal = ref(false)
const modalClose = () => {
showCreateSiteModal.value = false;
}
const formSite = ref(null)
const createSite = (formData) => {
store.dispatch('Site/save', formData).then((response) => {
if (response) {
formSite.value.clearFormData()
notification.success({message: t('save_success')});
showCreateSiteModal.value = false;
}
})
};
</script>
<style>
......
<template>
<div class="site-main space-top">
<div>
<div class="site-main space-top space-left space-right">
<div class="t-card-toolbar">
<div class="left">
{{ t("zentao_site") }}
</div>
<div class="right">
<Form labelCol="6" wrapperCol="16" class="site-search">
<FormItem
name="type"
:label="t('type')"
:info="validateInfos.enabled"
>
<select
name="type"
v-model="modelRef.enabled"
class="form-control"
>
<option
@change="onSearch"
v-for="item in statusArr"
:key="item.value"
:value="item.value"
>
{{ item.label }}
</option>
</select>
</FormItem>
<FormItem
name="keywords"
:label="t('input_keyword_to_search')"
:info="validateInfos.keywords"
>
<input
v-model="modelRef.keywords"
@change="onSearch"
@search="onSearch"
class="form-control"
/>
</FormItem>
</Form>
</div>
<Button
class="state primary"
size="sm"
@click="create()"
>
{{t('create_site')}}
</Button>
</div>
</div>
<div>
<Table
:is-loading="false"
:columns="columns"
:rows="models"
:isHidePaging="true"
:isSlotMode="true"
>
<template #status="record">
{{ disableStatus(record.value.disabled) }}
</template>
<template #createdAt="record">
<span v-if="record.value.createdAt">{{ momentUtc(record.value.createdAt) }}</span>
</template>
<template #action="record">
<a-button
v-if="record.value.url"
@click="() => edit(record.value.id)"
type="link"
size="small"
>{{ t("edit") }}</a-button
>
<a-button
v-if="record.value.url"
@click="() => remove(record)"
type="link"
size="small"
:loading="removeLoading.includes(record.value.seq)"
>{{ t("delete") }}
</a-button>
</template>
</Table>
</div>
<a-modal
:title="t('confirm_to_delete_site')"
v-if="confirmVisible"
:visible="true"
:destroy-on-close="true"
<Table
:is-loading="false"
:columns="columns"
:rows="models"
:isHidePaging="true"
:isSlotMode="true"
>
<template #footer>
<div :class="{ 't-dir-right': !isWin }" class="t-right">
<a-button
@click="removeConfirmed()"
type="primary"
class="t-btn-gap"
>{{ t("confirm") }}</a-button
>
<a-button @click="confirmVisible = false" class="t-btn-gap">{{
t("cancel")
}}</a-button>
</div>
<template #status="record">
{{ disableStatus(record.value.disabled) }}
</template>
<template #createdAt="record">
<span v-if="record.value.createdAt">{{
momentUtc(record.value.createdAt)
}}</span>
</template>
<template #action="record">
<Button
class="tab-setting-btn"
v-if="record.value.url"
@click="() => edit(record.value.id)"
size="sm"
>{{ t("edit") }}</Button
>
<Button
class="tab-setting-btn"
v-if="record.value.url"
@click="() => remove(record)"
size="sm"
>{{ t("delete") }}
</Button>
</template>
</a-modal>
</Table>
<FormSite
:show="showCreateSiteModal"
:id="editId"
@submit="createSite"
@cancel="modalClose"
ref="formSite"
/>
</div>
</template>
......@@ -116,28 +70,18 @@ import {
watch,
} from "vue";
import { useStore } from "vuex";
import { PlusCircleOutlined } from "@ant-design/icons-vue";
import { StateType } from "@/views/site/store";
import { useRouter } from "vue-router";
import { momentUtcDef } from "@/utils/datetime";
import { PaginationConfig, QueryParams } from "@/types/data";
import debounce from "lodash.debounce";
import { ZentaoData } from "@/store/zentao";
import { disableStatusDef } from "@/utils/decorator";
import { disableStatusMap } from "@/utils/const";
import { getInitStatus, setInitStatus } from "@/utils/cache";
import Table from "./Table.vue";
import { isWindows } from "@/utils/comm";
import Form from "./Form.vue";
import FormItem from "./FormItem.vue";
import { useForm } from "@/utils/form";
import notification from "@/utils/notification";
import Modal from "@/utils/modal";
import Button from "./Button.vue";
import FormSite from "./FormSite.vue";
const { t, locale } = useI18n();
const isWin = isWindows();
const momentUtc = momentUtcDef;
const disableStatus = disableStatusDef;
......@@ -145,31 +89,7 @@ const props = defineProps<{
tab: PageTab;
}>();
console.log(111111, props);
const modelRef = ref({});
const rulesRef = ref({
// name: [{ required: true, msg: t("pls_name") }],
});
const { validate, reset, validateInfos } = useForm(modelRef, rulesRef);
const submit = () => {
if (validate()) {
console.log("submit");
}
};
const localeConf = {} as any;
getInitStatus().then((initStatus) => {
console.log("initStatus", initStatus);
if (!initStatus) {
localeConf.emptyText = t("pls_add_zentao_site");
setTimeout(() => {
setInitStatus();
}, 1000);
}
});
const editId = ref(0);
onMounted(() => {
console.log("onMounted");
......@@ -191,53 +111,54 @@ const setColumns = () => {
isKey: true,
label: t("no"),
field: "index",
width: "8%",
},
{
label: t("name"),
field: "name",
width: "15%",
},
{
label: t("zentao_url"),
field: "url",
width: "15%",
},
{
label: t("username"),
field: "username",
width: "15%",
},
{
label: t("status"),
field: "status",
width: "15%",
},
{
label: t("create_time"),
field: "createdAt",
width: "15%",
},
{
label: t("opt"),
field: "action",
width: 260,
width: "10%",
},
];
};
setColumns();
const statusArr = ref(disableStatusMap);
const router = useRouter();
const zentaoStore = useStore<{ zentao: ZentaoData }>();
const store = useStore<{ Site: StateType }>();
const showCreateSiteModal = ref(false)
const models = computed<any[]>(() => store.state.Site.queryResult.result);
const pagination = computed<PaginationConfig>(
() => store.state.Site.queryResult.pagination
);
const queryParams = ref<QueryParams>({
keywords: "",
enabled: "1",
page: pagination.value.page,
pageSize: pagination.value.pageSize,
page: 1,
pageSize: 100,
});
const confirmVisible = ref(false);
const model = ref({} as any);
const loading = ref<boolean>(true);
......@@ -246,57 +167,62 @@ const list = (page: number) => {
store.dispatch("Site/list", {
keywords: queryParams.value.keywords,
enabled: queryParams.value.enabled,
pageSize: pagination.value.pageSize,
pageSize: queryParams.value.pageSize,
page: page,
});
loading.value = false;
};
list(1);
const onSearch = debounce(() => {
list(1);
}, 500);
onMounted(() => {
console.log("onMounted");
});
const create = () => {
console.log("create");
router.push(`/site/edit/0`);
editId.value = 0;
showCreateSiteModal.value = true;
};
const edit = (id) => {
console.log("edit");
router.push(`/site/edit/${id}`);
console.log("edit", id);
editId.value = id;
showCreateSiteModal.value = true;
};
const removeLoading = ref<string[]>([]);
const remove = (item) => {
model.value = item;
confirmVisible.value = true;
};
const removeConfirmed = async () => {
Modal.confirm({
title: '删除项目',
content: t('confirm_delete'),
okText: t('confirm'),
cancelText: t('cancel'),
onOk: async () => {
console.log('ok')
}
Modal.confirm({
title: "",
content: t("confirm_delete", {
name: item.value.name,
typ: t("zentao_site"),
}),
okText: t("confirm"),
cancelText: t("cancel"),
onOk: async () => {
store.dispatch("Site/delete", item.value.id).then((success) => {
zentaoStore.dispatch("Zentao/fetchSitesAndProduct").then((success) => {
notification.success(t("delete_success"));
list(1);
});
// removeLoading.value = [model.value.id];
// store.dispatch("Site/delete", model.value.id).then((success) => {
// zentaoStore.dispatch("Zentao/fetchSitesAndProduct").then((success) => {
// notification.success(t("delete_success"));
// list(pagination.value.page);
});
},
});
};
// removeLoading.value = [];
// confirmVisible.value = false;
// });
// });
const modalClose = () => {
showCreateSiteModal.value = false;
}
const formSite = ref(null)
const createSite = (formData) => {
store.dispatch('Site/save', formData).then((response) => {
if (response) {
formSite.value.clearFormData()
notification.success({message: t('save_success')});
showCreateSiteModal.value = false;
}
})
};
</script>
<style>
......@@ -322,8 +248,6 @@ const removeConfirmed = async () => {
width: 100%;
padding-right: 15px;
padding-left: 15px;
flex: 0 0 16.666667%;
max-width: 16.666667%;
padding-top: calc(0.375rem + 1px);
padding-bottom: calc(0.375rem + 1px);
margin-bottom: 0;
......@@ -332,7 +256,7 @@ const removeConfirmed = async () => {
.z-form-item {
display: flex;
align-items: center;
width: 100%;
word-break: keep-all;
}
.form-control:focus {
color: #495057;
......@@ -341,4 +265,14 @@ const removeConfirmed = async () => {
outline: 0;
box-shadow: 0 0 0 0.2rem rgb(0 123 255 / 25%);
}
.tab-setting-btn {
border: none;
background: none;
color: #1890ff;
border-style: hidden !important;
}
.t-card-toolbar{
display: flex;
justify-content: space-between;
}
</style>
\ No newline at end of file
......@@ -24,7 +24,7 @@ export function useForm(modelRef, rulesRef) {
if (pass && item.email) pass &&= checkEmail(key, item, model, errorMap)
if (pass && item.regex) pass &&= checkRegex(key, item, model, errorMap)
success = pass
success &&= pass
})
validateInfos.value[key] = errorMap
......
......@@ -5,6 +5,9 @@ const toast = useToast()
export default {
success(options) {
console.log(options)
if(typeof(options) === 'string') {
options = {message: options}
}
toast.success(options.message, options);
},
error(options) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册