20260805173201
This commit is contained in:
1 parent
7c9761a4fc
commit
bca59a2755
7 files changed
+812
-31
No files matched your search
@@ -1,7 +1,30 @@
|
||||
<script setup>
|
||||
import zhCN from "antdv-next/locale/zh_CN";
|
||||
|
||||
const themeConfig = {};
|
||||
const themeConfig = {
|
||||
token: {
|
||||
controlHeight: 28,
|
||||
},
|
||||
components: {
|
||||
Splitter: {
|
||||
splitBarSize: 1,
|
||||
},
|
||||
Button: {
|
||||
contentFontSize: 13,
|
||||
paddingInline: 10,
|
||||
},
|
||||
Form: {
|
||||
labelFontSize: 13,
|
||||
verticalLabelMargin: "0 0 2px",
|
||||
itemMarginBottom: 8,
|
||||
},
|
||||
Collapse: {
|
||||
headerBg: "#ffffff",
|
||||
contentBg: "#ffffff",
|
||||
borderlessContentBg: "#ffffff",
|
||||
},
|
||||
},
|
||||
};
|
||||
const timePickerLocale = {
|
||||
...zhCN.TimePicker,
|
||||
placeholder: "",
|
||||
@@ -45,3 +68,11 @@ const locale = {
|
||||
</a-app>
|
||||
</a-config-provider>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
/* 全局:按钮内图标跟随 contentFontSize(13px),覆盖 Lucide 的固定 size */
|
||||
.ant-btn svg {
|
||||
width: 1em !important;
|
||||
height: 1em !important;
|
||||
}
|
||||
</style>
|
||||
@@ -138,7 +138,7 @@ watch(() => props.queryItems, initializeDrafts, { immediate: true });
|
||||
:aria-label="appStore.t('common.search', '搜索')"
|
||||
@click="handleQuickSearch"
|
||||
>
|
||||
<Search :size="16" />
|
||||
<Search />
|
||||
</a-button>
|
||||
</a-space-compact>
|
||||
|
||||
@@ -152,7 +152,6 @@ watch(() => props.queryItems, initializeDrafts, { immediate: true });
|
||||
>
|
||||
<a-button
|
||||
shape="circle"
|
||||
class="toolbar-icon-button"
|
||||
:class="{ 'toolbar-icon-button--active': advancedOpen }"
|
||||
:aria-label="
|
||||
advancedOpen
|
||||
@@ -161,7 +160,7 @@ watch(() => props.queryItems, initializeDrafts, { immediate: true });
|
||||
"
|
||||
@click="toggleAdvancedSearch"
|
||||
>
|
||||
<Search :size="16" />
|
||||
<Search />
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
|
||||
@@ -172,17 +171,14 @@ watch(() => props.queryItems, initializeDrafts, { immediate: true });
|
||||
:trigger="['click']"
|
||||
placement="bottomRight"
|
||||
>
|
||||
<span class="more-trigger">
|
||||
<a-tooltip :title="appStore.t('common.more', '更多')">
|
||||
<a-button
|
||||
shape="circle"
|
||||
class="toolbar-icon-button"
|
||||
:aria-label="appStore.t('common.more', '更多')"
|
||||
>
|
||||
<Ellipsis :size="17" />
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</span>
|
||||
<a-tooltip :title="appStore.t('common.more', '更多')">
|
||||
<a-button
|
||||
shape="circle"
|
||||
:aria-label="appStore.t('common.more', '更多')"
|
||||
>
|
||||
<Ellipsis />
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
@@ -211,8 +207,8 @@ watch(() => props.queryItems, initializeDrafts, { immediate: true });
|
||||
class="query-more-toggle"
|
||||
@click="advancedMoreOpen = !advancedMoreOpen"
|
||||
>
|
||||
<ChevronUp v-if="advancedMoreOpen" :size="15" />
|
||||
<ChevronDown v-else :size="15" />
|
||||
<ChevronUp v-if="advancedMoreOpen" />
|
||||
<ChevronDown v-else />
|
||||
{{
|
||||
advancedMoreOpen
|
||||
? appStore.t("common.collapseConditions", "收起条件")
|
||||
@@ -223,11 +219,11 @@ watch(() => props.queryItems, initializeDrafts, { immediate: true });
|
||||
|
||||
<div class="query-actions">
|
||||
<a-button type="primary" :loading="loading" @click="handleAdvancedSearch">
|
||||
<Search :size="15" />
|
||||
<Search />
|
||||
{{ appStore.t("common.search", "查询") }}
|
||||
</a-button>
|
||||
<a-button type="text" :disabled="loading" @click="handleAdvancedReset">
|
||||
<RotateCcw :size="15" />
|
||||
<RotateCcw />
|
||||
{{ appStore.t("common.reset", "重置") }}
|
||||
</a-button>
|
||||
</div>
|
||||
@@ -294,14 +290,6 @@ watch(() => props.queryItems, initializeDrafts, { immediate: true });
|
||||
}
|
||||
|
||||
.toolbar-icon-button {
|
||||
display: inline-flex;
|
||||
width: 34px;
|
||||
min-width: 34px;
|
||||
height: 34px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
|
||||
&--active {
|
||||
border-color: #91caff;
|
||||
background: #e6f4ff;
|
||||
@@ -311,8 +299,6 @@ watch(() => props.queryItems, initializeDrafts, { immediate: true });
|
||||
|
||||
.more-trigger {
|
||||
display: inline-flex;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.query-panel {
|
||||
|
||||
@@ -25,6 +25,16 @@ const routes = [
|
||||
moduleId: "v_b_othercompany",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "base/othercompany/detail",
|
||||
name: "base-othercompany-detail",
|
||||
component: () => import("@/views/base/othercompany/detail.vue"),
|
||||
meta: {
|
||||
title: "合作伙伴详情",
|
||||
section: "基础数据",
|
||||
menuKey: "/base/othercompany",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "base/contact",
|
||||
name: "base-contact",
|
||||
@@ -36,6 +46,16 @@ const routes = [
|
||||
moduleId: "v_b_contact",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "base/contact/detail",
|
||||
name: "base-contact-detail",
|
||||
component: () => import("@/views/base/contact/detail.vue"),
|
||||
meta: {
|
||||
title: "联系人详情",
|
||||
section: "基础数据",
|
||||
menuKey: "/base/contact",
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "base/otherdata",
|
||||
name: "base-otherdata",
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { ArrowLeft } from "@lucide/vue";
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
const isCreate = computed(() => route.query.mode === "create");
|
||||
const recordId = computed(() => route.query.id || "");
|
||||
|
||||
function goBack() {
|
||||
router.push({ name: "base-contact" });
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="contact-detail">
|
||||
<div class="detail-header">
|
||||
<a-button type="text" @click="goBack">
|
||||
<ArrowLeft :size="16" />返回
|
||||
</a-button>
|
||||
<h2 class="detail-title">{{ isCreate ? "新增联系人" : "编辑联系人" }}</h2>
|
||||
</div>
|
||||
<div class="detail-body">
|
||||
<a-empty description="详细内容待实现" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.contact-detail {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: var(--fms-surface);
|
||||
border: 1px solid var(--fms-border);
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid var(--fms-border);
|
||||
}
|
||||
|
||||
.detail-title {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.detail-body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
padding: 24px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,10 +1,82 @@
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { message, Modal } from "antdv-next";
|
||||
import { Plus, Trash2 } from "@lucide/vue";
|
||||
import FmsModuleListPage from "@/components/fms-module-list/FmsModuleListPage.vue";
|
||||
import { usePermissionStore } from "@/stores/permissions";
|
||||
|
||||
const CONTACT_MODULE_CODE = "v_b_contact";
|
||||
|
||||
const permissionStore = usePermissionStore();
|
||||
const canCreateRow = computed(() => permissionStore.canPower(CONTACT_MODULE_CODE, "create"));
|
||||
const canDeleteRow = computed(() => permissionStore.canPower(CONTACT_MODULE_CODE, "delete"));
|
||||
|
||||
const moduleListRef = ref(null);
|
||||
const selectedRowKeys = ref([]);
|
||||
const dirtyCount = ref(0);
|
||||
const router = useRouter();
|
||||
|
||||
const rowSelection = computed(() => ({
|
||||
selectedRowKeys: selectedRowKeys.value,
|
||||
onChange: (keys) => {
|
||||
selectedRowKeys.value = keys;
|
||||
},
|
||||
}));
|
||||
|
||||
function goCreate() {
|
||||
if (canCreateRow.value) {
|
||||
router.push({ name: "base-contact-detail", query: { mode: "create" } });
|
||||
}
|
||||
}
|
||||
|
||||
function confirmBatchDelete() {
|
||||
if (!canDeleteRow.value || !selectedRowKeys.value.length) {
|
||||
message.warning("请先选择要删除的记录");
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: `确定删除选中的 ${selectedRowKeys.value.length} 条记录?`,
|
||||
content: "此操作不可恢复",
|
||||
okText: "删除",
|
||||
cancelText: "取消",
|
||||
okButtonProps: { danger: true },
|
||||
onOk: async () => {
|
||||
try {
|
||||
await moduleListRef.value?.deleteSelected?.(selectedRowKeys.value);
|
||||
selectedRowKeys.value = [];
|
||||
dirtyCount.value = 0;
|
||||
} finally {
|
||||
// noop
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="contact-page">
|
||||
<FmsModuleListPage data-code="v_b_contact" />
|
||||
<FmsModuleListPage
|
||||
ref="moduleListRef"
|
||||
data-code="v_b_contact"
|
||||
:row-selection="rowSelection"
|
||||
>
|
||||
<template #actions>
|
||||
<a-space>
|
||||
<a-button v-if="canCreateRow" type="primary" @click="goCreate">
|
||||
<Plus :size="15" />新增
|
||||
</a-button>
|
||||
<a-button
|
||||
v-if="canDeleteRow"
|
||||
danger
|
||||
:disabled="!selectedRowKeys.length"
|
||||
@click="confirmBatchDelete"
|
||||
>
|
||||
<Trash2 :size="15" />批量删除
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</FmsModuleListPage>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -0,0 +1,537 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { Save, RotateCcw, Trash2 } from "@lucide/vue";
|
||||
|
||||
const activeTab = ref("basic");
|
||||
|
||||
const tabItems = [
|
||||
{ key: "basic", label: "基本信息" },
|
||||
{ key: "contact", label: "联系信息" },
|
||||
{ key: "finance", label: "财务信息" },
|
||||
{ key: "business", label: "业务信息" },
|
||||
{ key: "attach", label: "附件" },
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!--
|
||||
IDEA 沉浸风 Demo
|
||||
核心思路:
|
||||
- 背景冷灰,无圆角无阴影,全贴边
|
||||
- 工具栏极窄,纯功能
|
||||
- 表单极致紧凑,冷色系
|
||||
-->
|
||||
<div class="idea-detail">
|
||||
<!-- 顶部工具栏:36px,纯功能 -->
|
||||
<div class="idea-toolbar">
|
||||
<span class="idea-toolbar-title">合作伙伴详情</span>
|
||||
<div class="idea-toolbar-actions">
|
||||
<a-button>
|
||||
<RotateCcw :size="15" />重置
|
||||
</a-button>
|
||||
<a-button danger>
|
||||
<Trash2 :size="15" />删除
|
||||
</a-button>
|
||||
<a-button type="primary">
|
||||
<Save :size="15" />保存
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab:极小高度,贴边 -->
|
||||
<div class="idea-tabs">
|
||||
<a-tabs v-model:active-key="activeTab" :items="tabItems" />
|
||||
</div>
|
||||
|
||||
<!-- 表单内容区 -->
|
||||
<div class="idea-body">
|
||||
<!-- ========== Tab: 基本信息 ========== -->
|
||||
<div v-show="activeTab === 'basic'" class="idea-form">
|
||||
<div class="idea-section">
|
||||
<div class="idea-section-label">基本信息</div>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="6">
|
||||
<a-form-item label="合作伙伴编码">
|
||||
<a-input placeholder="自动生成" disabled />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="合作伙伴名称" required>
|
||||
<a-input placeholder="请输入名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="简称">
|
||||
<a-input placeholder="请输入简称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="合作伙伴类型">
|
||||
<a-select placeholder="请选择类型" allow-clear>
|
||||
<a-select-option value="1">客户</a-select-option>
|
||||
<a-select-option value="2">供应商</a-select-option>
|
||||
<a-select-option value="3">代理商</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="客户级别">
|
||||
<a-select placeholder="请选择级别" allow-clear>
|
||||
<a-select-option value="A">A级</a-select-option>
|
||||
<a-select-option value="B">B级</a-select-option>
|
||||
<a-select-option value="C">C级</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="客户来源">
|
||||
<a-select placeholder="请选择来源" allow-clear>
|
||||
<a-select-option value="1">线上推广</a-select-option>
|
||||
<a-select-option value="2">线下展会</a-select-option>
|
||||
<a-select-option value="3">客户介绍</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
|
||||
<div class="idea-section">
|
||||
<div class="idea-section-label">区域信息</div>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="6">
|
||||
<a-form-item label="国家">
|
||||
<a-select placeholder="请选择国家" allow-clear>
|
||||
<a-select-option value="CN">中国</a-select-option>
|
||||
<a-select-option value="US">美国</a-select-option>
|
||||
<a-select-option value="JP">日本</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="省份">
|
||||
<a-input placeholder="请输入省份" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="城市">
|
||||
<a-input placeholder="请输入城市" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
|
||||
<div class="idea-section">
|
||||
<div class="idea-section-label">状态设置</div>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="6">
|
||||
<a-form-item label="是否启用">
|
||||
<a-switch checked-children="启用" un-checked-children="停用" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="排序号">
|
||||
<a-input-number placeholder="请输入排序号" :min="0" :style="{ width: '100%' }" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========== Tab: 联系信息 ========== -->
|
||||
<div v-show="activeTab === 'contact'" class="idea-form">
|
||||
<div class="idea-section">
|
||||
<div class="idea-section-label">主要联系人</div>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="6">
|
||||
<a-form-item label="联系人姓名">
|
||||
<a-input placeholder="请输入姓名" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="职位">
|
||||
<a-input placeholder="请输入职位" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="手机号码">
|
||||
<a-input placeholder="请输入手机号码" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="电子邮箱">
|
||||
<a-input placeholder="请输入邮箱" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
|
||||
<div class="idea-section">
|
||||
<div class="idea-section-label">地址信息</div>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="16">
|
||||
<a-form-item label="详细地址">
|
||||
<a-textarea placeholder="请输入详细地址" :rows="2" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="邮政编码">
|
||||
<a-input placeholder="请输入邮政编码" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========== Tab: 财务信息 ========== -->
|
||||
<div v-show="activeTab === 'finance'" class="idea-form">
|
||||
<div class="idea-section">
|
||||
<div class="idea-section-label">结算信息</div>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="6">
|
||||
<a-form-item label="结算币种">
|
||||
<a-select placeholder="请选择币种" allow-clear>
|
||||
<a-select-option value="CNY">人民币 (CNY)</a-select-option>
|
||||
<a-select-option value="USD">美元 (USD)</a-select-option>
|
||||
<a-select-option value="EUR">欧元 (EUR)</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="结算方式">
|
||||
<a-select placeholder="请选择结算方式" allow-clear>
|
||||
<a-select-option value="1">月结</a-select-option>
|
||||
<a-select-option value="2">票结</a-select-option>
|
||||
<a-select-option value="3">预付</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="付款条款">
|
||||
<a-select placeholder="请选择付款条款" allow-clear>
|
||||
<a-select-option value="1">预付</a-select-option>
|
||||
<a-select-option value="2">到付</a-select-option>
|
||||
<a-select-option value="3">月结30天</a-select-option>
|
||||
<a-select-option value="4">月结60天</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
|
||||
<div class="idea-section">
|
||||
<div class="idea-section-label">银行账户</div>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="6">
|
||||
<a-form-item label="开户银行">
|
||||
<a-input placeholder="请输入开户银行" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="银行账号">
|
||||
<a-input placeholder="请输入银行账号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="账户名称">
|
||||
<a-input placeholder="请输入账户名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="税号">
|
||||
<a-input placeholder="请输入税号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========== Tab: 业务信息 ========== -->
|
||||
<div v-show="activeTab === 'business'" class="idea-form">
|
||||
<div class="idea-section">
|
||||
<div class="idea-section-label">业务范围</div>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="主营业务">
|
||||
<a-select placeholder="请选择主营业务" mode="multiple" allow-clear>
|
||||
<a-select-option value="1">海运</a-select-option>
|
||||
<a-select-option value="2">空运</a-select-option>
|
||||
<a-select-option value="3">陆运</a-select-option>
|
||||
<a-select-option value="4">报关</a-select-option>
|
||||
<a-select-option value="5">仓储</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="合作状态">
|
||||
<a-select placeholder="请选择状态" allow-clear>
|
||||
<a-select-option value="1">合作中</a-select-option>
|
||||
<a-select-option value="2">暂停</a-select-option>
|
||||
<a-select-option value="3">终止</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
|
||||
<div class="idea-section">
|
||||
<div class="idea-section-label">备注信息</div>
|
||||
<a-form layout="vertical">
|
||||
<a-row :gutter="12">
|
||||
<a-col :span="16">
|
||||
<a-form-item label="备注">
|
||||
<a-textarea placeholder="请输入备注信息" :rows="3" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ========== Tab: 附件 ========== -->
|
||||
<div v-show="activeTab === 'attach'" class="idea-form">
|
||||
<a-empty description="暂无附件" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/*
|
||||
* Modern IDE 风格 v3
|
||||
* 参考:IDEA 2024 New UI / Linear / Vercel
|
||||
* 关键词:柔和、圆角、透明度、微妙阴影、过渡动画
|
||||
*/
|
||||
|
||||
// ═══ 颜色令牌 ═══
|
||||
$bg-root: #f1f3f5; // 根背景 — 暖灰偏冷
|
||||
$bg-toolbar: #ffffff; // 工具栏白
|
||||
$bg-tab: #f8f9fb; // Tab 区
|
||||
$bg-card: #ffffff; // 表单卡片
|
||||
$border: #e2e5e9; // 边框
|
||||
$border-light: #eceff3; // 淡边框
|
||||
$text: #111418; // 主文字
|
||||
$text-secondary: #5e6470; // 副文字
|
||||
$text-muted: #9098a5; // 淡文字
|
||||
$primary: #1a56db; // 主色
|
||||
$primary-soft: rgba(26, 86, 219, 0.06); // focus 光晕
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// 根容器
|
||||
// ═══════════════════════════════════════════
|
||||
.idea-detail {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: $bg-root;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// 工具栏
|
||||
// ═══════════════════════════════════════════
|
||||
.idea-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 40px;
|
||||
min-height: 40px;
|
||||
padding: 0 20px;
|
||||
flex-shrink: 0;
|
||||
background: rgba(255, 255, 255, 0.85);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.idea-toolbar-title {
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: $text-secondary;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.idea-toolbar-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// Tab 栏
|
||||
// ═══════════════════════════════════════════
|
||||
.idea-tabs {
|
||||
flex-shrink: 0;
|
||||
background: $bg-tab;
|
||||
padding: 0 20px;
|
||||
border-bottom: 1px solid $border-light;
|
||||
|
||||
:deep(.ant-tabs-nav) {
|
||||
margin-bottom: 0;
|
||||
|
||||
&::before {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-tabs-tab) {
|
||||
padding: 8px 16px;
|
||||
font-size: 13px;
|
||||
color: $text-muted;
|
||||
border-radius: 0;
|
||||
transition: color 0.15s ease;
|
||||
|
||||
&:hover {
|
||||
color: $text;
|
||||
}
|
||||
|
||||
&.ant-tabs-tab-active .ant-tabs-tab-btn {
|
||||
color: $text;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-tabs-ink-bar) {
|
||||
background: $primary;
|
||||
height: 2px;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
:deep(.ant-tabs-content-holder) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// 内容区
|
||||
// ═══════════════════════════════════════════
|
||||
.idea-body {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
padding: 24px;
|
||||
background: $bg-root;
|
||||
|
||||
&::-webkit-scrollbar { width: 6px; }
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: rgba(0, 0, 0, 0.12);
|
||||
border-radius: 3px;
|
||||
&:hover { background: rgba(0, 0, 0, 0.2); }
|
||||
}
|
||||
&::-webkit-scrollbar-track { background: transparent; }
|
||||
}
|
||||
|
||||
// 表单卡片
|
||||
.idea-form {
|
||||
max-width: 840px;
|
||||
margin: 0 auto;
|
||||
background: $bg-card;
|
||||
border-radius: 10px;
|
||||
padding: 32px 40px;
|
||||
box-shadow:
|
||||
0 0 0 1px rgba(0, 0, 0, 0.04),
|
||||
0 1px 2px rgba(0, 0, 0, 0.03),
|
||||
0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// Section
|
||||
// ═══════════════════════════════════════════
|
||||
.idea-section {
|
||||
margin-bottom: 28px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.idea-section-label {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: $text;
|
||||
letter-spacing: 0.02em;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid $border-light;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════
|
||||
// 表单控件 — 现代圆角、柔和边框
|
||||
// ═══════════════════════════════════════════
|
||||
:deep(.ant-form-item) {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
:deep(.ant-form-item-label) {
|
||||
padding-bottom: 4px;
|
||||
|
||||
> label {
|
||||
font-size: 13px;
|
||||
font-weight: 450;
|
||||
color: $text-secondary;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
// 输入框 / 选择器 — 6px 圆角,现代感
|
||||
:deep(.ant-input),
|
||||
:deep(.ant-input-affix-wrapper),
|
||||
:deep(.ant-select-selector),
|
||||
:deep(.ant-input-number) {
|
||||
font-size: 13px;
|
||||
border-radius: 6px;
|
||||
border-color: $border;
|
||||
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
||||
|
||||
&:hover {
|
||||
border-color: darken($border, 8%);
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.ant-input-number-input) {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
:deep(.ant-select-selection-item) {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
// Focus — 蓝色光晕
|
||||
:deep(.ant-input:focus),
|
||||
:deep(.ant-input-affix-wrapper-focused),
|
||||
:deep(.ant-select-focused .ant-select-selector),
|
||||
:deep(.ant-input-number-focused) {
|
||||
border-color: $primary;
|
||||
box-shadow: 0 0 0 3px $primary-soft;
|
||||
}
|
||||
|
||||
// disabled 态更柔和
|
||||
:deep(.ant-input-disabled),
|
||||
:deep(.ant-select-disabled .ant-select-selector) {
|
||||
background: #f8f9fb;
|
||||
color: $text-muted;
|
||||
}
|
||||
|
||||
// Switch 微调
|
||||
:deep(.ant-switch) {
|
||||
&.ant-switch-checked {
|
||||
background: $primary;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -6,14 +6,35 @@ import FmsModuleListPage from "@/components/fms-module-list/FmsModuleListPage.vu
|
||||
import FmsTree from "@/components/FmsTree.vue";
|
||||
import { escapeSqlText } from "@/components/fms-module-list/moduleListUtils";
|
||||
import { loadDataApi, nextIdApi, pageDataApi, saveObjectApi } from "@/services/api";
|
||||
import { usePermissionStore } from "@/stores/permissions";
|
||||
import { buildTree, sortTree } from "@/utils/tree";
|
||||
|
||||
const OTHERCOMPANY_MODULE_CODE = "v_b_othercompany";
|
||||
const ALL_CATEGORIES_KEY = "__fms_tree_root__";
|
||||
const categories = ref([]);
|
||||
const categoryLoading = ref(false);
|
||||
const selectedCategoryKey = ref(ALL_CATEGORIES_KEY);
|
||||
const expandedCategoryKeys = ref([ALL_CATEGORIES_KEY]);
|
||||
|
||||
const permissionStore = usePermissionStore();
|
||||
const canCreateRow = computed(() => permissionStore.canPower(OTHERCOMPANY_MODULE_CODE, "create"));
|
||||
const canUpdateRow = computed(() => permissionStore.canPower(OTHERCOMPANY_MODULE_CODE, "update"));
|
||||
const canDeleteRow = computed(() => permissionStore.canPower(OTHERCOMPANY_MODULE_CODE, "delete"));
|
||||
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const moduleListRef = ref(null);
|
||||
const selectedRowKeys = ref([]);
|
||||
const dirtyCount = ref(0);
|
||||
const router = useRouter();
|
||||
|
||||
const rowSelection = computed(() => ({
|
||||
selectedRowKeys: selectedRowKeys.value,
|
||||
onChange: (keys) => {
|
||||
selectedRowKeys.value = keys;
|
||||
},
|
||||
}));
|
||||
|
||||
const categoryById = computed(
|
||||
() => new Map(categories.value.map((item) => [String(item.b_id), item])),
|
||||
);
|
||||
@@ -368,6 +389,36 @@ async function confirmDeleteCategory(node) {
|
||||
});
|
||||
}
|
||||
|
||||
// ── 新增 / 批量删除 ──
|
||||
function goCreate() {
|
||||
if (canCreateRow.value) {
|
||||
router.push({ name: "base-othercompany-detail", query: { mode: "create" } });
|
||||
}
|
||||
}
|
||||
|
||||
function confirmBatchDelete() {
|
||||
if (!canDeleteRow.value || !selectedRowKeys.value.length) {
|
||||
message.warning("请先选择要删除的记录");
|
||||
return;
|
||||
}
|
||||
Modal.confirm({
|
||||
title: `确定删除选中的 ${selectedRowKeys.value.length} 条记录?`,
|
||||
content: "此操作不可恢复",
|
||||
okText: "删除",
|
||||
cancelText: "取消",
|
||||
okButtonProps: { danger: true },
|
||||
onOk: async () => {
|
||||
try {
|
||||
await moduleListRef.value?.deleteSelected?.(selectedRowKeys.value);
|
||||
selectedRowKeys.value = [];
|
||||
dirtyCount.value = 0;
|
||||
} finally {
|
||||
// noop
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadCategories();
|
||||
});
|
||||
@@ -396,10 +447,28 @@ onMounted(() => {
|
||||
<a-splitter-panel :min="520">
|
||||
<main class="partner-panel">
|
||||
<FmsModuleListPage
|
||||
ref="moduleListRef"
|
||||
data-code="v_b_othercompany"
|
||||
:fixed-search-condition="categoryFilterCondition"
|
||||
:column-extensions="columnExtensions"
|
||||
/>
|
||||
:row-selection="rowSelection"
|
||||
>
|
||||
<template #actions>
|
||||
<a-space>
|
||||
<a-button v-if="canCreateRow" type="primary" @click="goCreate">
|
||||
<Plus :size="15" />新增
|
||||
</a-button>
|
||||
<a-button
|
||||
v-if="canDeleteRow"
|
||||
danger
|
||||
:disabled="!selectedRowKeys.length"
|
||||
@click="confirmBatchDelete"
|
||||
>
|
||||
<Trash2 :size="15" />批量删除
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</FmsModuleListPage>
|
||||
</main>
|
||||
</a-splitter-panel>
|
||||
</a-splitter>
|
||||
|
||||
Reference in new issue
Block a user