import html, { getProp } from "html";
import request, { get, post } from "../../request/index.js";
import { defineAsyncComponent, ref, reactive, onMounted } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useI18n } from "vue-i18n";
import { listToTree, schemaToModel, importFunction } from "../../utils/index.js";
import qs from "../../lib/qs/shim.js";
import VueOfficeExcel from "@vue-office/excel";
import { camelCase, capitalize } from "lodash";
import { useAppStore } from "../../store/index.js";
export default {
name: "AppList",
components: {
AppForm: defineAsyncComponent(() => import("../form/index.js")),
SvgIcon: defineAsyncComponent(() => import("../../components/icon/index.js")),
AppFormInput: defineAsyncComponent(() => import("../form/form-input.js")),
VueOfficeExcel,
},
template: html`
{{item.meta.title}}
{{$t('筛选')}}
{{ (pageModel.pageIndex - 1) * pageModel.pageSize + scope.$index + 1 }}
{{ scope.row[key][subKey] }}
{{getProp(scope.row,item.navigation)}}
{{item.title}}
{{$t('operations')}}
{{item.meta.title}}
{{$t('filter')}}
o.checked=true)"> {{$t('selectAll')}}
o.checked=!o.checked)">
{{$t('selectInverse')}}
{{editFormTitle}}
{{$t('下载')}}
`,
styles: html``,
props: ["modelValue", "config", "querySchema", "controller", "query", "buttons"],
emits: ["command"],
setup(props, context) {
/*变量定义*/
// 配置
const config = reactive(props.config);
// 分页
const pageModel = reactive({
sizeList: [1, 50, 100],
pageIndex: 1,
pageSize: 10,
total: 0,
});
const treeProps = reactive({
children: "children",
});
const tableKey = ref(false);
const tableRef = ref(null);
const uploadRef = ref(null);
const columns = ref([]);
const filterDrawer = ref(false);
const subDrawer = ref(false);
const subListQuery = ref({});
const tableLoading = ref(true);
const selectedRows = ref([]);
const dialogVisible = ref(false);
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const appStore = useAppStore();
const buttons = ref(props.buttons ?? route.meta.children.filter((o) => o.meta.hasPermission));
const baseUrl = props.controller ?? `${route.meta.path}`;
const indexUrl = props.indexUrl ?? `${baseUrl}/index`;
const queryModel = ref({});
const sortColumns = ref(new Map());
const querySchema = ref(props.querySchema);
const queryList = ref([]);
const tableSchema = ref({});
const tableData = ref([]);
const editFormRef = ref(null);
const editFormloading = ref(false);
const editFormMode = ref(null);
const editFormTitle = ref("");
const editFormSchema = ref(null);
const editFormModel = ref(null);
const exportModel = reactive({
includeAll: false,
includeDeleted: false,
});
const importModel = reactive({
partial: true,
replace: false,
});
const fileList = ref([]);
const getSortModel = (model) => {
model.orderBy
.split(",")
.map((o) => o.trim())
.filter((o) => o)
.map((o) => ({
prop: camelCase(o.split(" ")[0]),
order: (o.split(" ").filter((o) => o)[1] ?? "asc") + "ending",
}))
.forEach((o) => sortColumns.value.set(o.prop, o.order));
};
const getColumns = (schema) => {
Object.keys(schema.properties).forEach((propertyName) => {
const property = schema.properties[propertyName];
if (property.type !== "object" && property.type !== "array" && !property.hidden && property.showForList) {
columns.value.push({ name: propertyName, title: property.title, checked: true });
}
});
};
const getClass = ({ row, column }) => {
if (column.property) {
column.order = sortColumns.value.get(column.property);
}
};
const sortChange = async ({ column, prop, order }) => {
if (order === null) {
sortColumns.value.delete(prop);
} else {
sortColumns.value.set(prop, order);
}
queryModel.value.orderBy = Array.from(sortColumns.value)
.map((o) => capitalize(o[0]) + (o[1] === "ascending" ? "" : ` DESC`))
.join(",");
await load();
};
const showColumn = (item, prop) => {
return (
item.type !== "object" &&
item.type !== "array" &&
!item.hidden &&
columns.value.findIndex((o) => o.name === prop && o.checked) >= 0
);
};
const handleSelectionChange = (rows) => (selectedRows.value = rows);
const load = async () => {
tableLoading.value = true;
try {
const url = config.query.url;
const method = config.query.method;
//
queryModel.value = schemaToModel(config.query.schema);
queryModel.value.maxResultCount = pageModel.pageSize;
queryModel.value.skipCount = (pageModel.pageIndex - 1) * pageModel.pageSize;
//
const postData = JSON.parse(JSON.stringify(queryModel.value));
postData.filters = queryList.value.filter((o) => o.property && o.value);
if (postData.items) {
delete postData["items"];
}
if (postData.query?.id) {
delete postData.query["id"];
}
const listData = (await request(url, postData, { method })).data;
const items = listData.items;
if (tableSchema.value.isTree) {
items = listToTree(listData.items);
}
tableData.value = items;
pageModel.total = listData.totalCount;
//data.value = listData;
tableKey.value = !tableKey.value;
} catch (error) {
console.log(error);
} finally {
tableLoading.value = false;
}
};
const onPageIndexChange = async () => await load();
const onPageSizeChange = async () => await load();
const click = async (item, rows) => {
editFormloading.value = true;
editFormMode.value = item.path ?? item;
context.emit("command", item, rows);
if (item.path === "index") {
//list
await load();
} else if (item.path === "details") {
//details
const url = `${baseUrl}/${item.path}?${qs.stringify({ id: rows[0].id })}`;
editFormSchema.value = (await get(url)).data;
editFormModel.value = (await post(url)).data;
editFormTitle.value = `${config.edit.schema.title}${t("details")}`;
dialogVisible.value = true;
} else if (item.path === "create" || item.path === "update") {
//create
if (item.path === "create") {
editFormModel.value = schemaToModel(config.edit.schema);
} else {
const url = `${config.edit.updateUrl ?? config.query.url}/${rows[0].id}`;
editFormModel.value = (await request(url, null, { method: "get" })).data;
}
editFormTitle.value = `${t(item.path)}${config.edit.schema.title}`;
dialogVisible.value = true;
} else if (item.path === "delete") {
//delete
if (item.meta.isTop) {
// 批量删除
return;
} else {
// 单个删除
}
const url = `${baseUrl}/${item.path}`;
// await post(
// url,
// rows.map((o) => o.id)
// );
await load();
} else if (item.path === "export") {
//export
editFormTitle.value = `${t(item.path)}${querySchema.value?.title}`;
dialogVisible.value = true;
} else if (item.path === "import") {
//import
const url = `${baseUrl}/${item.path}`;
editFormTitle.value = `${t(item.path)}${querySchema.value?.title}`;
fileList.value = [];
dialogVisible.value = true;
} else if (item === "filter") {
editFormTitle.value = t("自定义查询");
dialogVisible.value = true;
}
editFormloading.value = false;
};
const submit = async () => {
if (editFormMode.value === "create" || editFormMode.value === "update") {
try {
const valid = await editFormRef.value.validate();
if (valid) {
editFormloading.value = true;
const url =
(editFormMode.value === "create" ? config.edit.createUrl : config.edit.updateUrl) ?? config.query.url;
const method = editFormMode.value === "create" ? config.edit.createMethod : config.edit.updateMethod;
const result = await request(url, editFormModel.value, { method });
if (result.errors) {
model.errors = result.errors; //??
} else {
await load();
editFormMode.value = null;
dialogVisible.value = false;
}
}
} catch (error) {
console.log(error);
} finally {
editFormloading.value = false;
}
} else if (editFormMode.value === "details") {
dialogVisible.value = false;
editFormMode.value = null;
} else if (editFormMode.value === "export") {
const postData = JSON.parse(JSON.stringify(queryModel.value));
postData.filters = queryList.value.filter((o) => o.property && o.value);
delete postData.query["items"];
delete postData.query["id"];
const url = `${baseUrl}/${editFormMode.value}?${qs.stringify(exportModel)}`;
const response = await post(url, postData);
download(response);
dialogVisible.value = false;
} else if (editFormMode.value === "import") {
editFormloading.value = true;
const url = `${baseUrl}/${editFormMode.value}`;
const formData = new FormData();
formData.append("partial", importModel.partial);
formData.append("replace", importModel.replace);
formData.append("file", fileList.value[0]?.raw);
console.log(uploadRef.value);
const response = await post(url, formData);
editFormloading.value = false;
dialogVisible.value = false;
await load();
} else if (editFormMode.value === "filter") {
await load();
dialogVisible.value = false;
}
};
const showList = (value, nav) => {
if (!subDrawer.value) {
const controller = nav.substr(0, nav.lastIndexOf(".")).toLowerCase();
const findRoute = (tree) => {
for (const item of tree) {
if (item.meta.controller === controller) {
return item;
}
if (item.children) {
return findRoute(item.children);
}
}
};
const targetRoute = router.getRoutes().find((o) => o.meta?.controller === controller);
subListQuery.value = {
controller,
query: { [camelCase(nav.substr(nav.lastIndexOf(".") + 1))]: value },
buttons: targetRoute.meta.buttons,
};
subDrawer.value = true;
}
};
const pushQueryList = () => {
queryList.value.push({
property: "",
operator: "{0}=@0",
value: "",
logic: "and",
});
};
const download = (response) => {
const downloadUrl = window.URL.createObjectURL(response.data);
const filename = response.filename;
let link = document.createElement("a");
link.href = downloadUrl;
link.download = filename;
link.click();
window.URL.revokeObjectURL(downloadUrl);
};
const getImportTemplate = async () => {
const url = `${baseUrl}/${editFormMode.value}`;
const response = await get(url);
download(response);
};
const handleChange = (uploadFile, uploadFiles) => {
fileList.value = uploadFiles;
};
const getButtonDisabled = async (src, row) => {
if (src) {
const method = await importFunction(src);
return src.startsWith("async") ? await method(row) : method(row);
}
return false;
};
onMounted(async () => {
for (const item of route.meta.children) {
if (item.meta.disabled?.constructor === String) {
item.meta.disabled = await importFunction(item.meta.disabled);
}
}
pushQueryList();
// if (!querySchema.value) {
// const vm = (await get(indexUrl)).data;
// querySchema.value = vm.schema.properties.query;
// tableSchema.value = vm.schema.properties.items.items;
// data.value = vm.model ?? schemaToModel(vm.schema);
// if (props.query) {
// Object.assign(data.value.query, props.query);
// }
// getSortModel(data.value);
// getColumns(vm.schema.properties.query);
// }
if (!config) {
//
}
getColumns(config.table.schema);
if (props.query) {
Object.assign(queryModel.value.query, props.query);
}
// getSortModel(data.value);
// getColumns(vm.schema.properties.query);
await load();
});
return {
config,
queryModel,
pageModel,
treeProps,
tableKey,
tableRef,
uploadRef,
tableLoading,
columns,
showColumn,
filterDrawer,
subDrawer,
dialogVisible,
selectedRows,
querySchema,
queryList,
tableSchema,
buttons,
tableData,
getClass,
sortChange,
getProp,
getImportTemplate,
editFormRef,
editFormloading,
editFormMode,
editFormTitle,
editFormSchema,
editFormModel,
exportModel,
importModel,
onPageSizeChange,
onPageIndexChange,
handleSelectionChange,
load,
click,
submit,
showList,
subListQuery,
pushQueryList,
fileList,
handleChange,
getButtonDisabled,
};
},
};