Commit 373a242f authored by 李明环(东信)'s avatar 李明环(东信)

表单组件 创建工作步骤1

parent 10eb7e7a
......@@ -8,7 +8,7 @@
"files.eol": "\n",
"typescript.tsdk": "node_modules/typescript/lib",
"[vue]": {
"editor.defaultFormatter": "octref.vetur"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
......
<template>
<div class="form-item" :style="{ borderWidth: props.border ? '2rpx' : '0' }">
<p class="title">{{ props.title }}</p>
<img v-if="icon" class="icon" :src="iconPath" alt="" />
<slot></slot>
</div>
</template>
<script setup lang="ts">
const props = defineProps({
// 标题
title: {
type: String,
default: () => "默认title"
},
// 边框
border: {
type: Boolean,
default: () => true
},
// 图标 (如果为空不显示)
icon: {
type: String as PropType<"arrow" | "edit" | "">,
default: () => "arrow"
}
});
const iconPath = new URL(`../../static/image/icon/${props.icon}.png`, import.meta.url).href;
</script>
<style lang="scss" scoped>
.form-item {
position: relative;
padding-bottom: 16rpx;
margin-top: 32rpx;
border-bottom: 2rpx solid rgb(31 35 41 / 15%);
.title {
margin-bottom: 32rpx;
font-size: 32rpx;
font-weight: 600;
line-height: 36rpx;
}
.icon {
position: absolute;
right: 20rpx;
bottom: 24rpx;
width: 28rpx;
height: 28rpx;
}
}
</style>
<template>
<div class="form-row" :style="{ gridTemplateColumns: props.fill ? '1fr' : '1fr 1fr' }">
<slot></slot>
</div>
</template>
<script setup>
const props = defineProps({
fill: {
type: Boolean,
default: () => true
}
});
</script>
<style lang="scss" scoped>
.form-row {
display: grid;
}
</style>
<template>
<div class="selectbox">
<div
v-for="v in props.options"
:class="{ item: true, active: isActive(v) }"
:key="v[props.valueKey]"
@click="onClickItem(v)"
>
{{ v[props.labelKey] }}
</div>
</div>
</template>
<script setup>
const props = defineProps({
// 默认值
modelValue: {
type: [String, Number, Array],
default: () => ""
},
//值的键
valueKey: {
type: String,
default: () => "value"
},
//label的键
labelKey: {
type: String,
default: () => "label"
},
// 是否多选
multiple: {
type: Boolean,
default: () => false
},
// 默认值
options: {
type: Array,
default: () => []
}
});
const emit = defineEmits(["update:modelValue"]);
// 激活类名
const isActive = e => {
if (props.multiple) {
return props.modelValue.includes(e[props.valueKey]);
} else {
return props.modelValue === e[props.valueKey];
}
};
// 点击选项
const onClickItem = e => {
const value = e[props.valueKey];
if (props.multiple) {
const index = props.modelValue.indexOf(value);
if (index > -1) {
emit("update:modelValue", props.modelValue.slice(index, 1));
} else {
emit("update:modelValue", [...props.modelValue, value]);
}
} else {
emit("update:modelValue", value);
}
};
</script>
<style lang="scss" scoped>
.selectbox {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
.item {
display: flex;
align-items: center;
justify-content: center;
height: 32px;
font-size: 12px;
color: #1f86ff;
background: #1f86ff0f;
border-radius: 4px;
}
.active {
color: #ffffff;
background: #1f86ff;
}
}
</style>
@import "wot-design-uni/components/common/abstracts/variable";
@import "wot-design-uni/components/common/abstracts/mixin";
.wot-theme-dark {
@include b(col-picker) {
@include when(border) {
.wd-col-picker__cell {
@include halfPixelBorder("top", $-cell-padding, $-dark-border-color);
}
}
@include e(label) {
color: $-dark-color;
}
@include e(cell) {
color: $-dark-color;
background-color: $-dark-background2;
@include when(disabled) {
.wd-col-picker__value {
color: $-dark-color3;
}
}
}
@include e(list-item) {
@include when(disabled) {
color: $-dark-color3;
}
}
@include e(list-item-tip) {
color: $-dark-color-gray;
}
@include e(value) {
color: $-dark-color;
@include m(placeholder) {
color: $-dark-color-gray;
}
}
:deep(.wd-col-picker__arrow) {
color: $-dark-color;
}
@include e(list) {
color: $-dark-color;
}
@include e(selected) {
color: $-dark-color;
}
}
}
.tags {
gap: 32rpx;
padding: 0 32rpx;
div {
padding: 8rpx 16rpx;
font-size: 24rpx;
color: #4d80f0;
background-color: #4d80f01f;
}
}
@include b(col-picker) {
@include when(border) {
.wd-col-picker__cell {
@include halfPixelBorder("top", $-cell-padding);
}
}
@include e(cell) {
position: relative;
display: flex;
align-items: flex-start;
padding: $-cell-wrapper-padding $-cell-padding;
overflow: hidden;
font-size: $-cell-title-fs;
line-height: $-cell-line-height;
color: $-cell-title-color;
text-decoration: none;
background-color: $-color-white;
}
@include e(cell) {
@include when(disabled) {
.wd-col-picker__value {
color: $-input-disabled-color;
}
}
@include when(align-right) {
.wd-col-picker__value {
text-align: right;
}
}
@include when(error) {
.wd-col-picker__value {
color: $-input-error-color;
}
:deep(.wd-col-picker__arrow) {
color: $-input-error-color;
}
}
@include when(large) {
font-size: $-cell-title-fs-large;
:deep(.wd-col-picker__arrow) {
font-size: $-cell-icon-size-large;
}
}
}
@include e(error-message) {
font-size: $-form-item-error-message-font-size;
line-height: $-form-item-error-message-line-height;
color: $-form-item-error-message-color;
text-align: left;
vertical-align: middle;
}
@include e(label) {
position: relative;
box-sizing: border-box;
width: $-input-cell-label-width;
margin-right: $-cell-padding;
color: $-cell-title-color;
@include when(required) {
padding-left: 12px;
&::after {
position: absolute;
top: 2px;
left: 0;
font-size: $-cell-required-size;
line-height: 1.1;
color: $-cell-required-color;
content: "*";
}
}
}
@include e(value-wraper) {
display: flex;
}
@include e(value) {
flex: 1;
margin-right: 10px;
color: $-cell-value-color;
@include when(ellipsis) {
@include lineEllipsis;
}
@include m(placeholder) {
color: $-input-placeholder-color;
}
}
@include e(body) {
flex: 1;
}
@include edeep(arrow) {
display: block;
font-size: $-cell-icon-size;
line-height: $-cell-line-height;
color: $-cell-arrow-color;
}
@include e(selected) {
height: $-col-picker-selected-height;
overflow: hidden;
font-size: $-col-picker-selected-fs;
color: $-col-picker-selected-color;
}
@include e(selected-container) {
position: relative;
display: flex;
user-select: none;
}
@include e(selected-item) {
flex: 0 0 auto;
height: $-col-picker-selected-height;
padding: $-col-picker-selected-padding;
line-height: $-col-picker-selected-height;
@include when(selected) {
font-weight: $-col-picker-selected-fw;
}
}
@include e(selected-line) {
position: absolute;
bottom: 5px;
left: 0;
z-index: 1;
width: $-col-picker-line-width;
height: $-col-picker-line-height;
background: $-col-picker-line-color;
border-radius: calc($-col-picker-line-height / 2);
box-shadow: $-col-picker-line-box-shadow;
}
@include e(list-container) {
position: relative;
}
@include e(list) {
box-sizing: border-box;
height: $-col-picker-list-height;
padding-bottom: $-col-picker-list-padding-bottom;
overflow: auto;
font-size: $-col-picker-list-fs;
color: $-col-picker-list-color;
-webkit-overflow-scrolling: touch;
}
@include e(list-item) {
display: flex;
align-items: flex-start;
padding: $-col-picker-list-item-padding;
@include when(selected) {
color: $-col-picker-list-color-checked;
:deep(.wd-col-picker__checked) {
opacity: 1;
}
}
@include when(disabled) {
color: $-col-picker-list-color-disabled;
}
}
@include e(list-item-label) {
line-height: 1.285;
}
@include e(list-item-tip) {
margin-top: 2px;
font-size: $-col-picker-list-fs-tip;
color: $-col-picker-list-color-tip;
}
@include edeep(checked) {
display: block;
margin-left: 4px;
font-size: $-col-picker-list-checked-icon-size;
color: $-col-picker-list-color-checked;
opacity: 0;
}
@include e(loading) {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
}
}
import type { ComponentPublicInstance, ExtractPropTypes, PropType } from "vue";
import {
baseProps,
makeArrayProp,
makeBooleanProp,
makeNumberProp,
makeRequiredProp,
makeStringProp
} from "wot-design-uni/components/common/props";
import type { FormItemRule } from "wot-design-uni/components/wd-form/types";
export const colPickerProps = {
...baseProps,
/**
* 选中项
*/
modelValue: makeRequiredProp(Array as PropType<Array<string | number>>),
/* 多选数据 */
mValue: {
type: Array,
default: () => []
},
mMax: {
type: Number,
default: 1
},
/**
* 选择器数据,二维数组
*/
columns: makeArrayProp<Record<string, any>[]>(),
/**
* 选择器左侧文案
*/
label: String,
/**
* 设置左侧标题宽度
*/
labelWidth: makeStringProp("33%"),
/**
* 使用 label 插槽时设置该选项
*/
useLabelSlot: makeBooleanProp(false),
/**
* 使用默认插槽时设置该选项
*/
useDefaultSlot: makeBooleanProp(false),
/**
* 禁用
*/
disabled: makeBooleanProp(false),
/**
* 只读
*/
readonly: makeBooleanProp(false),
/**
* 选择器占位符
*/
placeholder: String,
/**
* 弹出层标题
*/
title: String,
/**
* 接收当前列的选中项 item、当前列下标、当前列选中项下标下一列数据处理函数 resolve、结束选择 finish
*/
columnChange: Function as PropType<ColPickerColumnChange>,
/**
* 自定义展示文案的格式化函数,返回一个字符串
*/
displayFormat: Function as PropType<ColPickerDisplayFormat>,
/**
* 确定前校验函数,接收 (value, resolve) 参数,通过 resolve 继续执行 picker,resolve 接收 1 个 boolean 参数
*/
beforeConfirm: Function as PropType<ColPickerBeforeConfirm>,
/**
* 选择器的值靠右展示
*/
alignRight: makeBooleanProp(false),
/**
* 是否为错误状态,错误状态时右侧内容为红色
*/
error: makeBooleanProp(false),
/**
* 是否必填
*/
required: makeBooleanProp(false),
/**
* 设置选择器大小,可选值:large
*/
size: String,
/**
* 选项对象中,value 对应的 key
*/
valueKey: makeStringProp("value"),
/**
* 选项对象中,展示的文本对应的 key
*/
labelKey: makeStringProp("label"),
/**
* 选项对象中,提示文案对应的 key
*/
tipKey: makeStringProp("tip"),
/**
* loading 图标的颜色
*/
loadingColor: makeStringProp("#4D80F0"),
/**
* 点击遮罩是否关闭
*/
closeOnClickModal: makeBooleanProp(true),
/**
* 自动触发 column-change 事件来补全数据,当 columns 为空数组或者 columns 数组长度小于 value 数组长度时,会自动触发 column-change
*/
autoComplete: makeBooleanProp(false),
/**
* 弹窗层级
*/
zIndex: makeNumberProp(15),
/**
* 弹出面板是否设置底部安全距离(iphone X 类型的机型)
*/
safeAreaInsetBottom: makeBooleanProp(true),
/**
* 是否超出隐藏
*/
ellipsis: makeBooleanProp(false),
/**
* 表单域 model 字段名,在使用表单校验功能的情况下,该属性是必填的
*/
prop: String,
/**
* 表单验证规则,结合wd-form组件使用
*/
rules: makeArrayProp<FormItemRule>(),
/**
* label 外部自定义样式
*/
customViewClass: makeStringProp(""),
/**
* value 外部自定义样式
*/
customLabelClass: makeStringProp(""),
customValueClass: makeStringProp("")
};
export type ColPickerProps = ExtractPropTypes<typeof colPickerProps>;
export type ColPickerColumnChangeOption = {
selectedItem: Record<string, any>;
index: number;
rowIndex: number;
addMValue: Function;
resolve: (nextColumn: Record<string, any>[]) => void;
finish: (isOk?: boolean) => void;
};
export type ColPickerColumnChange = (option: ColPickerColumnChangeOption) => void;
export type ColPickerDisplayFormat = (selectedItems: Record<string, any>[]) => string;
export type ColPickerBeforeConfirm = (
value: (string | number)[],
selectedItems: Record<string, any>[],
resolve: (isPass: boolean) => void
) => void;
export type ColPickerExpose = {
// 关闭picker弹框
close: () => void;
// 打开picker弹框
open: () => void;
};
export type ColPickerInstance = ComponentPublicInstance<ColPickerExpose, ColPickerProps>;
This diff is collapsed.
......@@ -6,9 +6,35 @@
<view class="t2">选择对应的职位并填写职位信息</view>
</view>
<view class="content">
<view class="switch">
<!-- <view class="active">全职</view>
<view>兼职</view> -->
<selectbox :options="typeOptions" v-model="typeValue"></selectbox>
<form-row>
<form-item title="职位类型">
<wd-col-picker
v-model="value"
:columns="columns"
:column-change="columnChange"
@confirm="handleConfirm"
label-key="name"
value-key="id"
use-default-slot
>
<view :class="`inner flex-between ${pinias.formData.jobTypeText ? '' : 'placeholder'}`">
{{ pinias.formData.jobTypeText || "请选择职位类型" }}
</view>
</wd-col-picker>
</form-item>
</form-row>
<form-row>
<form-item title="职位标题" icon="edit">
<input type="text" placeholder="输入职位标题如“财务总监”" />
</form-item>
</form-row>
<form-row>
<form-item title="职位描述" :border="false" icon="">
<textarea></textarea>
</form-item>
</form-row>
<!-- <view class="switch">
<view
v-for="(item, index) in EnumWorkMode"
:class="item.code == pinias.formData.workMode ? 'active' : ''"
......@@ -16,8 +42,8 @@
:key="index"
>{{ item.text }}
</view>
</view>
<view class="form-item">
</view> -->
<!-- <view class="form-item">
<view class="form-item-title">职位类型</view>
<wd-col-picker
v-model="value"
......@@ -33,8 +59,8 @@
<view class="arrow"></view>
</view>
</wd-col-picker>
</view>
<view class="form-item">
</view> -->
<!-- <view class="form-item">
<view class="form-item-title">职位标题</view>
<view class="inner flex-between">
<input
......@@ -44,8 +70,8 @@
placeholder="请输入职业标题"
/>
</view>
</view>
<view class="form-item describe" style="border: 0">
</view> -->
<!-- <view class="form-item describe" style="border: 0">
<view class="form-item-title">职位描述</view>
<wd-textarea
custom-class="textarea"
......@@ -54,12 +80,9 @@
v-model="pinias.formData.jobDesc"
placeholder="请输入你的职位描述"
/>
</view>
</view> -->
</view>
<!-- <view class="btn-wrap">
<button class="bottom-btn" @tap="next">下一步</button>
</view> -->
<wd-tabbar
@tap="next"
custom-style="display: flex;justify-content: center !important;z-index:1;"
......@@ -81,6 +104,10 @@ import { validateForm } from "@/utils/utils";
import _ from "lodash";
import { useReleasePostionStore } from "./store";
import FormItem from "@/components/form/form-item.vue";
import FormRow from "@/components/form/form-row.vue";
import Selectbox from "@/components/form/selectbox.vue";
const pinias = useReleasePostionStore();
onLoad(option => {
......@@ -139,11 +166,33 @@ const next = () => {
});
}
};
/* 类型 */
const typeValue = ref(1);
const typeOptions = [
{
label: "全职",
value: 1
},
{
label: "兼职",
value: 2
},
{
label: "见习",
value: 3
},
{
label: "实习",
value: 4
}
];
</script>
<style lang="scss" scoped>
@import "./common.scss";
.describe {
/* .describe {
textarea {
box-sizing: border-box;
width: 686rpx;
......@@ -156,21 +205,20 @@ const next = () => {
}
.page {
.textarea {
max-height: 272rpx;
margin-top: 32rpx;
background: #f2f5fb;
max-height: 272rpx;
:deep(.wd-textarea__value) {
background: #f2f5fb !important;
max-height: 272rpx;
width: 100%;
max-height: 272rpx;
padding: 0 !important;
background: #f2f5fb !important;
}
:deep(.wd-textarea__count) {
background: none !important;
}
}
}
.switch {
display: flex;
align-items: center;
......@@ -189,8 +237,14 @@ const next = () => {
background-color: #1f86ff;
}
}
} */
textarea {
box-sizing: border-box;
width: 100%;
padding: 32rpx;
background: #f2f5fb;
border-radius: 8rpx;
}
.foot-btn {
position: fixed;
display: flex;
......
......@@ -36,7 +36,7 @@
<wd-icon @click="handleClose" name="close" size="30rpx"></wd-icon>
</view>
<wd-picker-view @change="handleConfirm" use-default-slot :columns="columns" v-model="value"></wd-picker-view>
<view style="width: 100%; display: flex; justify-content: center"
<view style="display: flex; justify-content: center; width: 100%"
><wd-button style="width: 80%" @click="handleClose" block :round="false">确定</wd-button></view
>
</wd-popup>
......@@ -283,11 +283,11 @@ initViewData();
border-radius: 50% !important;
}
.title-box {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 32rpx;
box-sizing: border-box;
}
.welfare {
display: flex;
......@@ -339,7 +339,6 @@ picker-view {
justify-content: space-around;
color: #cccccc;
}
.foot-btn {
position: fixed;
display: flex;
......
......@@ -172,7 +172,6 @@ initViewData();
<style lang="scss" scoped>
@import "./common.scss";
.foot-btn {
position: fixed;
display: flex;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment