Przeglądaj źródła

标签属性页面优化

吴树波 15 godzin temu
rodzic
commit
07a75a2c84

+ 326 - 224
src/views/crm/components/addOrEditCustomer.vue

@@ -1,65 +1,107 @@
 <template>
-    <div>
-        <el-form ref="form" :model="form" :rules="rules" label-width="120px">
-                <!-- <el-form-item label="客户编码" prop="customerCode">
-                    <el-input v-model="form.customerCode" :disabled="form.customerId!=null" placeholder="请输入客户编码" />
-                </el-form-item> -->
-                <el-form-item label="客户名称" prop="customerName">
-                    <el-input v-model="form.customerName" placeholder="请输入客户名称" />
-                </el-form-item>
-                <el-form-item label="手机" prop="mobile">
-                    <el-input  maxlength="11" v-model="form.mobile" placeholder="请输入手机" />
-                </el-form-item>
-                <el-form-item label="性别" prop="sex">
-                    <el-radio-group v-model="form.sex">
-                        <el-radio :label="item.dictValue" v-for="item in sexOptions" >{{item.dictLabel}}</el-radio>
-                    </el-radio-group>
-                </el-form-item>
-                <el-form-item label="微信号" prop="weixin">
-                    <el-input v-model="form.weixin" placeholder="请输入微信号" />
-                </el-form-item>
-                <el-form-item label="所在地区" prop="address">
-                    <el-cascader
-                    ref="citySelect"
-                    v-model="cityIds"
-                    :options="citys"
-                    @change="handleCityChange"></el-cascader>
-                </el-form-item>
-                <el-form-item label="详细地址" prop="detailAddress">
-                    <el-input v-model="form.detailAddress" placeholder="请输入详细地址" />
-                </el-form-item>
-                <el-form-item label="客户类型" prop="customerType">
-                    <el-select v-model="form.customerType" placeholder="请选择客户类型" clearable size="small">
-                        <el-option
-                            v-for="item in typeOptions"
-                            :key="item.dictValue"
-                            :label="item.dictLabel"
-                            :value="item.dictValue"
+    <div class="customer-dialog-content">
+        <div class="dialog-header">
+            <i class="el-icon-user header-icon"></i>
+            <span class="header-title">{{ form.customerId ? '编辑客户' : '新增客户' }}</span>
+        </div>
+        
+        <el-form ref="form" :model="form" :rules="rules" label-width="120px" class="customer-form">
+            <el-divider content-position="left">
+                <span class="divider-title">
+                    <i class="el-icon-info"></i> 基本信息
+                </span>
+            </el-divider>
+            
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="客户名称" prop="customerName">
+                        <el-input v-model="form.customerName" placeholder="请输入客户名称" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="手机" prop="mobile">
+                        <el-input maxlength="11" v-model="form.mobile" placeholder="请输入手机" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="性别" prop="sex">
+                        <el-radio-group v-model="form.sex">
+                            <el-radio :label="item.dictValue" v-for="item in sexOptions" :key="item.dictValue">{{item.dictLabel}}</el-radio>
+                        </el-radio-group>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="微信号" prop="weixin">
+                        <el-input v-model="form.weixin" placeholder="请输入微信号" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="客户类型" prop="customerType">
+                        <el-select v-model="form.customerType" placeholder="请选择客户类型" clearable style="width: 100%;">
+                            <el-option
+                                v-for="item in typeOptions"
+                                :key="item.dictValue"
+                                :label="item.dictLabel"
+                                :value="item.dictValue"
                             />
-                    </el-select>
-                </el-form-item>
-                <!-- <el-form-item label="客户状态">
-                    <el-radio-group v-model="form.status">
-                        <el-radio :label="item.dictValue" v-for="item in statusOptions">{{item.dictLabel}}</el-radio>
-                    </el-radio-group>
-                </el-form-item> -->
-                <el-form-item label="客户来源" prop="source">
-                <el-select v-model="form.source" placeholder="请选择客户来源" clearable size="small">
-                    <el-option
-                        v-for="item in sourceOptions"
-                        :key="item.dictValue"
-                        :label="item.dictLabel"
-                        :value="item.dictValue"
-                        />
-                </el-select>
-                </el-form-item>
-                <el-form-item label="标签" prop="tags">
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="客户来源" prop="source">
+                        <el-select v-model="form.source" placeholder="请选择客户来源" clearable style="width: 100%;">
+                            <el-option
+                                v-for="item in sourceOptions"
+                                :key="item.dictValue"
+                                :label="item.dictLabel"
+                                :value="item.dictValue"
+                            />
+                        </el-select>
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="所在地区" prop="address">
+                        <el-cascader
+                            ref="citySelect"
+                            v-model="cityIds"
+                            :options="citys"
+                            @change="handleCityChange"
+                            style="width: 100%;"
+                        ></el-cascader>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="详细地址" prop="detailAddress">
+                        <el-input v-model="form.detailAddress" placeholder="请输入详细地址" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            
+            <el-divider content-position="left">
+                <span class="divider-title">
+                    <i class="el-icon-price-tag"></i> 标签信息
+                </span>
+            </el-divider>
+            
+            <el-form-item label="标签" prop="tags">
+                <div class="tags-container">
                     <el-tag
                         :key="tag"
                         v-for="tag in tags"
                         closable
                         :disable-transitions="false"
-                        @close="handleClose(tag)">
+                        class="selected-tag"
+                        @close="handleClose(tag)"
+                    >
                         {{tag}}
                     </el-tag>
                     <el-input
@@ -68,110 +110,147 @@
                         v-model="inputValue"
                         ref="saveTagInput"
                         size="small"
+                        placeholder="输入新标签"
                         @keyup.enter.native="handleInputConfirm"
                         @blur="handleInputConfirm"
                     >
                     </el-input>
-                    <el-button v-else class="button-new-tag" size="small" @click="showInput">添加标签+</el-button>
-                    <el-select v-model="tagId" @change="tagsChange" style="width:140px;margin-left: 5px;" placeholder="请选择客户标签" clearable size="small">
+                    <el-button v-else class="button-new-tag" size="small" icon="el-icon-plus" @click="showInput">自定义标签</el-button>
+                    <el-select v-model="tagId" @change="tagsChange" style="width:140px;margin-left: 10px;" placeholder="选择标签" clearable size="small">
                         <el-option
                             v-for="item in tagsOptions"
                             :key="item.dictValue"
                             :label="item.dictLabel"
                             :value="item.dictValue"
-                            />
+                        />
                     </el-select>
-                </el-form-item>
-                <el-form-item label="进线日期" prop="registerDate">
-                <el-date-picker
-                value-format="yyyy-MM-dd"
-                    v-model="form.registerDate"
-                    type="date"
-                    placeholder="请选择进线日期">
-                </el-date-picker>
-                </el-form-item>
-                <el-form-item label="进线链接" prop="registerLinkUrl">
-                <el-input v-model="form.registerLinkUrl" placeholder="请输入进线链接" />
-                </el-form-item>
-                <el-form-item label="进线客户详情" prop="registerDesc">
-                    <el-input v-model="form.registerDesc" placeholder="请输入进线客户详情" />
-                </el-form-item>
-                <el-form-item label="进线填写时间" prop="registerSubmitTime">
-                <el-date-picker
-                    value-format="yyyy-MM-dd HH:mm:ss"
-                    v-model="form.registerSubmitTime"
-                    type="datetime"
-                    placeholder="请选择进线填写时间">
-                </el-date-picker>
-                </el-form-item>
-                <el-form-item label="进线方式" prop="registerType">
-                    <el-input v-model="form.registerType" placeholder="请输入进线方式" />
-                </el-form-item>
-                <el-form-item label="来源渠道编码" prop="sourceCode">
-                    <el-input v-model="form.sourceCode" placeholder="请输入来源渠道编码" />
-                </el-form-item>
-                <el-form-item label="推线时间" prop="pushTime">
-                    <el-input v-model="form.pushTime" placeholder="请输入推线时间" />
-                </el-form-item>
-                <el-form-item label="推线编码" prop="pushCode">
-                    <el-input v-model="form.pushCode" placeholder="请输入推线编码" />
-                </el-form-item>
-                <el-form-item :label="ext.name" v-for="ext  in exts"  >
-                    <el-input v-model="ext.value"  />
-                </el-form-item>
-
-                <el-form-item label="备注" prop="remark">
-                    <el-input :rows="2" v-model="form.remark" type="textarea" placeholder="请输入内容" />
-                </el-form-item>
-            </el-form>
-            <div  class="footer">
-                <el-button type="primary" @click="submitForm">确 定</el-button>
-            </div>
+                </div>
+            </el-form-item>
+            
+            <el-divider content-position="left">
+                <span class="divider-title">
+                    <i class="el-icon-connection"></i> 进线信息
+                </span>
+            </el-divider>
+            
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="进线日期" prop="registerDate">
+                        <el-date-picker
+                            value-format="yyyy-MM-dd"
+                            v-model="form.registerDate"
+                            type="date"
+                            placeholder="请选择进线日期"
+                            style="width: 100%;"
+                        ></el-date-picker>
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="进线填写时间" prop="registerSubmitTime">
+                        <el-date-picker
+                            value-format="yyyy-MM-dd HH:mm:ss"
+                            v-model="form.registerSubmitTime"
+                            type="datetime"
+                            placeholder="请选择进线填写时间"
+                            style="width: 100%;"
+                        ></el-date-picker>
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="进线链接" prop="registerLinkUrl">
+                        <el-input v-model="form.registerLinkUrl" placeholder="请输入进线链接" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="进线方式" prop="registerType">
+                        <el-input v-model="form.registerType" placeholder="请输入进线方式" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            
+            <el-form-item label="进线客户详情" prop="registerDesc">
+                <el-input v-model="form.registerDesc" placeholder="请输入进线客户详情" />
+            </el-form-item>
+            
+            <el-row :gutter="20">
+                <el-col :span="12">
+                    <el-form-item label="来源渠道编码" prop="sourceCode">
+                        <el-input v-model="form.sourceCode" placeholder="请输入来源渠道编码" />
+                    </el-form-item>
+                </el-col>
+                <el-col :span="12">
+                    <el-form-item label="推线时间" prop="pushTime">
+                        <el-input v-model="form.pushTime" placeholder="请输入推线时间" />
+                    </el-form-item>
+                </el-col>
+            </el-row>
+            
+            <el-form-item label="推线编码" prop="pushCode">
+                <el-input v-model="form.pushCode" placeholder="请输入推线编码" />
+            </el-form-item>
+            
+            <el-divider content-position="left" v-if="exts.length > 0">
+                <span class="divider-title">
+                    <i class="el-icon-s-operation"></i> 扩展信息
+                </span>
+            </el-divider>
+            
+            <el-form-item :label="ext.name" v-for="ext in exts" :key="ext.extId">
+                <el-input v-model="ext.value" placeholder="请输入内容" />
+            </el-form-item>
+            
+            <el-divider content-position="left">
+                <span class="divider-title">
+                    <i class="el-icon-document"></i> 备注
+                </span>
+            </el-divider>
+            
+            <el-form-item label="备注" prop="remark">
+                <el-input :rows="3" v-model="form.remark" type="textarea" placeholder="请输入备注内容" maxlength="500" show-word-limit />
+            </el-form-item>
+        </el-form>
     </div>
 </template>
   
 <script>
     import { listCustomerExt } from "@/api/crm/customerExt";
-    import { updateCustomer,addCustomer,addMyCustomer,getCustomerDetails   } from "@/api/crm/customer";
-    import {getCitys} from "@/api/store/city";
+    import { updateCustomer, addCustomer, addMyCustomer, getCustomerDetails } from "@/api/crm/customer";
+    import { getCitys } from "@/api/store/city";
+    
     export default {
-        name: "remark",
+        name: "AddOrEditCustomer",
         data() {
             return {
-                addType:1,//添加类型 1线索客户 2我的客户
-                tagId:null,
-                tagsOptions:[],
-                cityIds:[],
-                citys:[],
-                tags:[],
+                addType: 1,
+                tagId: null,
+                tagsOptions: [],
+                cityIds: [],
+                citys: [],
+                tags: [],
                 inputVisible: false,
                 inputValue: '',
-                statusOptions:[],
-                typeOptions:[],
-                sourceOptions:[],
-                sexOptions:[],
-                customerExts:[],
-                // 表单参数
+                statusOptions: [],
+                typeOptions: [],
+                sourceOptions: [],
+                sexOptions: [],
+                customerExts: [],
                 form: {
-                    province:null,
-                    city:null,
-                    district:null,
-                    
+                    province: null,
+                    city: null,
+                    district: null,
                 },
-                exts:[],
-                // 表单校验
+                exts: [],
                 rules: {
-                    // customerName: [
-                    // { required: true, message: "客户名称不能为空", trigger: "blur" }
-                    // ],
                     mobile: [
-                    { required: true, message: "手机号不能为空", trigger: "blur" }
+                        { required: true, message: "手机号不能为空", trigger: "blur" }
                     ],
                     source: [
-                    { required: true, message: "客户来源不能为空", trigger: "blur" }
+                        { required: true, message: "客户来源不能为空", trigger: "blur" }
                     ],
                 }
-                 
             };
         },
         created() {
@@ -190,44 +269,32 @@
             this.getDicts("crm_customer_type").then((response) => {
                 this.typeOptions = response.data;
             });
-            
-            this.getCitys()
+            this.getCitys();
         },
         methods: {
-            tagsChange(e){
-                var item=this.tagsOptions.find(val => val.dictValue === e);
-                console.log(item);
-                this.tags.push(item.dictLabel);
-                this.form.tags=this.tags.toString();
-            },
-            closeTag(){
-                this.addTag.open=false;
-                this.getDetails(this.customerId)
-            },
-            handleAddTag(){
-                this.addTag.open=true;
-                var that=this;
-                setTimeout(() => {
-                    that.$refs.tag.reset(this.item);
-                }, 500);
-                
+            tagsChange(e) {
+                var item = this.tagsOptions.find(val => val.dictValue === e);
+                if (item && !this.tags.includes(item.dictLabel)) {
+                    this.tags.push(item.dictLabel);
+                    this.form.tags = this.tags.toString();
+                }
+                this.tagId = null;
             },
             handleCityChange(value) {
-                console.log(value);
-                var nodes=this.$refs.citySelect.getCheckedNodes();
-                this.form.address=nodes[0].pathLabels[0]+"-"+nodes[0].pathLabels[1]+"-"+nodes[0].pathLabels[2];
-                this.form.cityIds=value.toString();
-                console.log(this.form.address);
+                var nodes = this.$refs.citySelect.getCheckedNodes();
+                if (nodes && nodes.length > 0) {
+                    this.form.address = nodes[0].pathLabels.join("-");
+                    this.form.cityIds = value.toString();
+                }
             },
-            getCitys(){
+            getCitys() {
                 getCitys().then(res => {
-                this.loading = false;
-                this.citys=res.data;
-                })
+                    this.citys = res.data;
+                });
             },
             handleClose(tag) {
                 this.tags.splice(this.tags.indexOf(tag), 1);
-                this.form.tags=this.tags.toString();
+                this.form.tags = this.tags.toString();
             },
             showInput() {
                 this.inputVisible = true;
@@ -236,15 +303,14 @@
                 });
             },
             handleInputConfirm() {
-                let inputValue = this.inputValue;
-                if (inputValue) {
+                let inputValue = this.inputValue.trim();
+                if (inputValue && !this.tags.includes(inputValue)) {
                     this.tags.push(inputValue);
+                    this.form.tags = this.tags.toString();
                 }
                 this.inputVisible = false;
                 this.inputValue = '';
-                this.form.tags=this.tags.toString();
             },
-            // 表单重置
             reset() {
                 this.form = {
                     customerId: null,
@@ -276,113 +342,100 @@
                     isLine: null,
                     source: null,
                     tags: null,
-                    
                 };
-                this.exts=[];
-                this.tags=[];
-                this.cityIds=[];
+                this.exts = [];
+                this.tags = [];
+                this.cityIds = [];
                 this.resetForm("form");
             },
             handleAdd(addType) {
-                this.addType=addType;
+                this.addType = addType;
                 this.reset();
-                console.log(this.customerExts)
-                var data={status:1}
+                var data = { status: 1 };
                 listCustomerExt(data).then(response => {
                     this.customerExts = response.data;
                     this.customerExts.forEach(element => {
-                        var data={extId:element.extId,name:element.name,value:""};
-                        this.exts.push(data)
+                        var data = { extId: element.extId, name: element.name, value: "" };
+                        this.exts.push(data);
                     });
-                
                 });
-                
-                console.log(this.exts)
             },
-            /** 修改按钮操作 */
             handleUpdate(customerId) {
                 this.reset();
-                var that=this;
-                var data={customerId:customerId}
+                var that = this;
+                var data = { customerId: customerId };
                 getCustomerDetails(data).then(response => {
                     this.form = response.customer;
-                    if(this.form.status!=null){
+                    if (this.form.status != null) {
                         this.form.status = this.form.status.toString();
                     }
-                    if(this.form.customerType!=null){
+                    if (this.form.customerType != null) {
                         this.form.customerType = this.form.customerType.toString();
                     }
-                    if(this.form.sex!=null){
-                     this.form.sex = this.form.sex.toString();
+                    if (this.form.sex != null) {
+                        this.form.sex = this.form.sex.toString();
                     }
-                    if(this.form.source!=null){
+                    if (this.form.source != null) {
                         this.form.source = this.form.source.toString();
                     }
-                    if(this.form.tags!=null){
-                        this.tags = this.form.tags.split(",")
+                    if (this.form.tags != null) {
+                        this.tags = this.form.tags.split(",");
                     }
-                    if(this.form.cityIds!=null){
-                        var ids=this.form.cityIds.split(",");
-                        this.cityIds=[];
+                    if (this.form.cityIds != null) {
+                        var ids = this.form.cityIds.split(",");
+                        this.cityIds = [];
                         ids.forEach(element => {
-                            var id=parseInt(element);
-                            that.cityIds.push(id)
+                            var id = parseInt(element);
+                            that.cityIds.push(id);
                         });
                     }
                     listCustomerExt(data).then(response => {
                         this.customerExts = response.data;
                         this.customerExts.forEach(element => {
-                            var data={extId:element.extId,name:element.name,value:""};
-                            this.exts.push(data)
+                            var data = { extId: element.extId, name: element.name, value: "" };
+                            this.exts.push(data);
                         });
-                        if(this.form.extJson!=null){
-                            var extList=JSON.parse(this.form.extJson);
+                        if (this.form.extJson != null) {
+                            var extList = JSON.parse(this.form.extJson);
                             that.exts.forEach(item => {
                                 extList.forEach(element => {
-                                    if(item.extId==element.extId){
-                                        item.value=element.value
+                                    if (item.extId == element.extId) {
+                                        item.value = element.value;
                                     }
                                 });
-                            
                             });
                         }
-                    
                     });
-                    this.open = true;
-                    this.title = "修改客户";
                 });
             },
-            /** 提交按钮 */
             submitForm() {
                 this.$refs["form"].validate(valid => {
                     if (valid) {
                         if (this.form.customerId != null) {
-                            this.form.extJson=JSON.stringify(this.exts);
+                            this.form.extJson = JSON.stringify(this.exts);
                             updateCustomer(this.form).then(response => {
                                 if (response.code === 200) {
-                                    this.msgSuccess("操作成功");
+                                    this.$message.success("操作成功");
                                     this.$emit('close');
                                 }
                             });
                         } else {
-                            this.form.extJson=JSON.stringify(this.exts);
-                            if(this.addType==1){
+                            this.form.extJson = JSON.stringify(this.exts);
+                            if (this.addType == 1) {
                                 addCustomer(this.form).then(response => {
                                     if (response.code === 200) {
-                                        this.msgSuccess("操作成功");
+                                        this.$message.success("操作成功");
                                         this.$emit('close');
                                     }
                                 });
-                            }
-                            else if(this.addType==2){
+                            } else if (this.addType == 2) {
                                 addMyCustomer(this.form).then(response => {
                                     if (response.code === 200) {
-                                        this.msgSuccess("操作成功");
+                                        this.$message.success("操作成功");
                                         this.$emit('close');
                                     }
                                 });
                             }
-                            
                         }
                     }
                 });
@@ -391,19 +444,68 @@
     };
 </script>
 <style lang="scss" scoped>
-.contents{
-    height: 100%;
-    background-color: #fff;
-    padding: 20px;
+.customer-dialog-content {
+    padding: 10px 0;
+    
+    .dialog-header {
+        display: flex;
+        align-items: center;
+        margin-bottom: 24px;
         
-}
-.footer{
-    display: flex;
-    align-items: center;
-    justify-content: flex-end;
+        .header-icon {
+            font-size: 24px;
+            color: #409eff;
+            margin-right: 12px;
+        }
+        
+        .header-title {
+            font-size: 16px;
+            font-weight: 600;
+            color: #303133;
+        }
+    }
+    
+    .customer-form {
+        .el-divider {
+            margin: 20px 0;
+            
+            .divider-title {
+                font-size: 14px;
+                font-weight: 600;
+                color: #606266;
+                display: flex;
+                align-items: center;
+                gap: 6px;
+                
+                i {
+                    color: #909399;
+                }
+            }
+        }
+        
+        .tags-container {
+            display: flex;
+            flex-wrap: wrap;
+            gap: 8px;
+            align-items: center;
+            min-height: 40px;
+        }
+        
+        .selected-tag {
+            margin: 0;
+        }
+        
+        .button-new-tag {
+            background: #f5f7fa;
+            border: 1px dashed #d9d9d9;
+            color: #606266;
+            
+            &:hover {
+                background: #ecf5ff;
+                border-color: #409eff;
+                color: #409eff;
+            }
+        }
+    }
 }
 </style>
-
-
-
- 

+ 42 - 28
src/views/crm/components/addRemark.vue

@@ -1,20 +1,29 @@
 <template>
-    <div>
-            <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-                <el-form-item label="备注" prop="remark">
-                    <el-input :rows="2" v-model="form.remark" type="textarea" placeholder="请输入内容" />
-                </el-form-item>
-            </el-form>
-            <div  class="footer">
-                <el-button type="primary" @click="submitForm">确 定</el-button>
-            </div>
+    <div class="remark-dialog-content">
+        <div class="dialog-header">
+            <i class="el-icon-document header-icon"></i>
+            <span class="header-title">添加客户备注</span>
+        </div>
+        
+        <el-form ref="form" :model="form" :rules="rules" label-width="80px" class="remark-form">
+            <el-form-item label="备注内容" prop="remark">
+                <el-input 
+                    :rows="5" 
+                    v-model="form.remark" 
+                    type="textarea" 
+                    placeholder="请输入备注内容..."
+                    maxlength="500"
+                    show-word-limit
+                />
+            </el-form-item>
+        </el-form>
     </div>
 </template>
   
 <script>
     import { updateCustomer  } from "@/api/crm/customer";
     export default {
-        name: "remark",
+        name: "AddRemark",
         data() {
             return {
                 form: {
@@ -22,12 +31,12 @@
                     remark:null,
                  
                 },
-                // 表单校验
                 rules: {
                     remark: [
-                        { required: true, message: "备注不能为空", trigger: "change" }
+                        { required: true, message: "请输入备注内容", trigger: "blur" },
+                        { min: 2, message: "备注内容至少2个字符", trigger: "blur" }
                     ],
-         
+             
                 }
                  
             };
@@ -44,8 +53,7 @@
                     if (valid) {
                         updateCustomer(this.form).then(response => {
                             if (response.code === 200) {
-                                this.msgSuccess("操作成功");
-                                
+                                this.$message.success("操作成功");
                                 this.$emit('close');
                             }
                         });
@@ -56,19 +64,25 @@
     };
 </script>
 <style lang="scss" scoped>
-.contents{
-    height: 100%;
-    background-color: #fff;
-    padding: 20px;
+.remark-dialog-content {
+    padding: 10px 0;
+    
+    .dialog-header {
+        display: flex;
+        align-items: center;
+        margin-bottom: 24px;
         
-}
-.footer{
-    display: flex;
-    align-items: center;
-    justify-content: flex-end;
+        .header-icon {
+            font-size: 24px;
+            color: #909399;
+            margin-right: 12px;
+        }
+        
+        .header-title {
+            font-size: 16px;
+            font-weight: 600;
+            color: #303133;
+        }
+    }
 }
 </style>
-
-
-
- 

+ 95 - 48
src/views/crm/components/addTag.vue

@@ -1,22 +1,29 @@
 <template>
-    <div>
-            <el-form ref="form" :model="form" :rules="rules" label-width="80px">
-                <el-form-item label="标签库" >
-                    <el-select @change="tagChange" v-model="tag" placeholder="请选择" clearable size="small">
-                        <el-option
-                                v-for="item in tagsOptions"
-                                :key="item.dictValue"
-                                :label="item.dictLabel"
-                                :value="item.dictValue"
-                            />
-                    </el-select>
-                </el-form-item>
-                <el-form-item label="标签" prop="tags">
+    <div class="tag-dialog-content">
+        <div class="dialog-header">
+            <i class="el-icon-price-tag header-icon"></i>
+            <span class="header-title">为客户添加标签</span>
+        </div>
+        
+        <el-form ref="form" :model="form" :rules="rules" label-width="80px" class="tag-form">
+            <el-form-item label="标签库">
+                <el-select @change="tagChange" v-model="tag" placeholder="从标签库选择" clearable size="medium" style="width: 100%;">
+                    <el-option
+                            v-for="item in tagsOptions"
+                            :key="item.dictValue"
+                            :label="item.dictLabel"
+                            :value="item.dictValue"
+                        />
+                </el-select>
+            </el-form-item>
+            <el-form-item label="已选标签" prop="tags">
+                <div class="tags-container">
                     <el-tag
                         :key="tag"
                         v-for="tag in tags"
                         closable
                         :disable-transitions="false"
+                        class="selected-tag"
                         @close="handleClose(tag)">
                         {{tag}}
                     </el-tag>
@@ -26,23 +33,26 @@
                         v-model="inputValue"
                         ref="saveTagInput"
                         size="small"
+                        placeholder="输入新标签"
                         @keyup.enter.native="handleInputConfirm"
                         @blur="handleInputConfirm"
                     >
                     </el-input>
-                    <el-button v-else class="button-new-tag" size="small" @click="showInput">添加标签+</el-button>
-                </el-form-item>
-            </el-form>
-            <div  class="footer">
-                <el-button type="primary" @click="submitForm">确 定</el-button>
-            </div>
+                    <el-button v-else class="button-new-tag" size="small" icon="el-icon-plus" @click="showInput">自定义标签</el-button>
+                </div>
+                <div class="form-tip" v-if="tags.length === 0">
+                    <i class="el-icon-info"></i>
+                    <span>请从标签库选择或自定义添加标签</span>
+                </div>
+            </el-form-item>
+        </el-form>
     </div>
 </template>
   
 <script>
     import { updateCustomer  } from "@/api/crm/customer";
     export default {
-        name: "visit",
+        name: "AddTag",
         data() {
             return {
                 tag:null,
@@ -55,12 +65,11 @@
                     tags:null,
                  
                 },
-                // 表单校验
                 rules: {
                     tags: [
-                        { required: true, message: "标签不能为空", trigger: "change" }
+                        { required: true, message: "请至少选择一个标签", trigger: "change" }
                     ],
-         
+             
                 }
                  
             };
@@ -69,17 +78,15 @@
             this.getDicts("crm_customer_tag").then((response) => {
                 this.tagsOptions = response.data;
             });
-            
-            
         },
         methods: {
             tagChange(e){
-                console.log(e)
                 var v=this.tagsOptions.find(value=>value.dictValue==e);
-                console.log(v)
-                this.tags.push(v.dictLabel);
-                this.form.tags=this.tags.toString();
-
+                if (v && !this.tags.includes(v.dictLabel)) {
+                    this.tags.push(v.dictLabel);
+                    this.form.tags=this.tags.toString();
+                }
+                this.tag = null;
             },
             reset(customer) {
                 this.tags= [];
@@ -100,21 +107,20 @@
                 });
             },
             handleInputConfirm() {
-                let inputValue = this.inputValue;
-                if (inputValue) {
+                let inputValue = this.inputValue.trim();
+                if (inputValue && !this.tags.includes(inputValue)) {
                     this.tags.push(inputValue);
+                    this.form.tags=this.tags.toString();
                 }
                 this.inputVisible = false;
                 this.inputValue = '';
-                this.form.tags=this.tags.toString();
             },
             submitForm() {
                 this.$refs["form"].validate(valid => {
                     if (valid) {
                         updateCustomer(this.form).then(response => {
                             if (response.code === 200) {
-                                this.msgSuccess("操作成功");
-                                
+                                this.$message.success("操作成功");
                                 this.$emit('close');
                             }
                         });
@@ -125,19 +131,60 @@
     };
 </script>
 <style lang="scss" scoped>
-.contents{
-    height: 100%;
-    background-color: #fff;
-    padding: 20px;
+.tag-dialog-content {
+    padding: 10px 0;
+    
+    .dialog-header {
+        display: flex;
+        align-items: center;
+        margin-bottom: 24px;
         
-}
-.footer{
-    display: flex;
-    align-items: center;
-    justify-content: flex-end;
+        .header-icon {
+            font-size: 24px;
+            color: #e6a23c;
+            margin-right: 12px;
+        }
+        
+        .header-title {
+            font-size: 16px;
+            font-weight: 600;
+            color: #303133;
+        }
+    }
+    
+    .tag-form {
+        .tags-container {
+            display: flex;
+            flex-wrap: wrap;
+            gap: 8px;
+            align-items: center;
+            min-height: 40px;
+        }
+        
+        .selected-tag {
+            margin: 0;
+        }
+        
+        .button-new-tag {
+            background: #f5f7fa;
+            border: 1px dashed #d9d9d9;
+            color: #606266;
+            
+            &:hover {
+                background: #ecf5ff;
+                border-color: #409eff;
+                color: #409eff;
+            }
+        }
+        
+        .form-tip {
+            margin-top: 8px;
+            font-size: 12px;
+            color: #909399;
+            display: flex;
+            align-items: center;
+            gap: 4px;
+        }
+    }
 }
 </style>
-
-
-
- 

+ 16 - 4
src/views/crm/components/customerDetails.vue

@@ -327,17 +327,29 @@
         </div>
 
         <!-- 弹窗 -->
-        <el-dialog :title="addTag.title" :visible.sync="addTag.open" width="600px" append-to-body>
+        <el-dialog :title="addTag.title" :visible.sync="addTag.open" width="600px" append-to-body :show-close="true" class="customer-dialog">
             <add-tag ref="tag" @close="closeTag()"></add-tag>
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="addTag.open = false">取 消</el-button>
+                <el-button type="primary" @click="$refs.tag.submitForm()">确 定</el-button>
+            </span>
         </el-dialog>
-        <el-dialog :title="addRemark.title" :visible.sync="addRemark.open" width="600px" append-to-body>
+        <el-dialog :title="addRemark.title" :visible.sync="addRemark.open" width="600px" append-to-body :show-close="true" class="customer-dialog">
             <add-remark ref="remark" @close="closeRemark()"></add-remark>
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="addRemark.open = false">取 消</el-button>
+                <el-button type="primary" @click="$refs.remark.submitForm()">确 定</el-button>
+            </span>
         </el-dialog>
-        <el-dialog :title="addSms.title" :visible.sync="addSms.open" width="800px" append-to-body>
+        <el-dialog :title="addSms.title" :visible.sync="addSms.open" width="800px" append-to-body class="customer-dialog">
             <add-sms ref="sms" @close="closeSms()"></add-sms>
         </el-dialog>
-        <el-dialog :title="customer.title" :visible.sync="customer.open" width="1000px" append-to-body>
+        <el-dialog :title="customer.title" :visible.sync="customer.open" width="1000px" append-to-body :show-close="true" class="customer-dialog">
             <add-or-edit-customer ref="customer" @close="closeCustomer()"></add-or-edit-customer>
+            <span slot="footer" class="dialog-footer">
+                <el-button @click="customer.open = false">取 消</el-button>
+                <el-button type="primary" @click="$refs.customer.submitForm()">确 定</el-button>
+            </span>
         </el-dialog>
         <el-drawer size="75%" :modal="false" :title="duplicate.title" :visible.sync="duplicate.open">
             <duplicate-customer ref="duplicateCustomer"/>