基本成型
This commit is contained in:
26
miniprogram/pages/publish/publish.json
Normal file
26
miniprogram/pages/publish/publish.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"component": true,
|
||||
"navigationBarTitleText": "发布投票文章",
|
||||
"usingComponents": {
|
||||
"van-field": "@vant/weapp/field/index",
|
||||
"van-radio": "@vant/weapp/radio/index",
|
||||
"van-radio-group": "@vant/weapp/radio-group/index",
|
||||
"van-icon": "@vant/weapp/icon/index",
|
||||
|
||||
"t-tabs": "tdesign-miniprogram/tabs/tabs",
|
||||
"t-tab-panel": "tdesign-miniprogram/tab-panel/tab-panel",
|
||||
"t-input": "tdesign-miniprogram/input/input",
|
||||
"t-radio": "tdesign-miniprogram/radio/radio",
|
||||
"t-radio-group": "tdesign-miniprogram/radio-group/radio-group",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-cell": "tdesign-miniprogram/cell/cell",
|
||||
"t-date-time-picker": "tdesign-miniprogram/date-time-picker/date-time-picker",
|
||||
"t-button": "tdesign-miniprogram/button/button",
|
||||
"t-picker": "tdesign-miniprogram/picker/picker",
|
||||
"t-picker-item": "tdesign-miniprogram/picker-item/picker-item"
|
||||
|
||||
},
|
||||
"navigationBarBackgroundColor": "#ffffff",
|
||||
"navigationBarTextStyle": "black"
|
||||
|
||||
}
|
||||
265
miniprogram/pages/publish/publish.ts
Normal file
265
miniprogram/pages/publish/publish.ts
Normal file
@@ -0,0 +1,265 @@
|
||||
Page({
|
||||
data: {
|
||||
// 表单数据(与需求字段对应)
|
||||
form: {
|
||||
title: "", // 文章标题
|
||||
vote_type: "single", // 投票类型:single-单选,multiple-多选
|
||||
end_time: "", // 结束时间(ISO格式,如:2025-10-22T00:59:59+08:00)
|
||||
end_time_format: "", // 结束时间(展示用,如:2025-10-22 00:59)
|
||||
options: [
|
||||
{ content: "", sort_order: 1 }, // 默认1个选项,sort_order自动生成
|
||||
],
|
||||
},
|
||||
showTimePicker: false, // 时间选择器弹窗显隐
|
||||
currentTime: new Date().getTime(), // 当前选择的时间
|
||||
minDate: new Date().getTime(), // 最小可选时间(当前时间)
|
||||
isSubmitting: false, // 提交状态
|
||||
style: 'border: 2rpx solid var(--td-component-border);border-radius: 12rpx;',
|
||||
value: 0,
|
||||
value1: 0,
|
||||
|
||||
mode: '',
|
||||
datetimeVisible: false,
|
||||
datetime: new Date().getTime(),
|
||||
datetimeText: '',
|
||||
cityText: '',
|
||||
cityValue: [],
|
||||
citys: [
|
||||
{ label: '用户邀请码', value: '用户邀请码' },
|
||||
],
|
||||
|
||||
},
|
||||
|
||||
// 1. 输入框通用处理(标题)
|
||||
handleInput(e) {
|
||||
const { key } = e.currentTarget.dataset;
|
||||
this.setData({
|
||||
[`form.${key}`]: e.detail.value,
|
||||
});
|
||||
},
|
||||
|
||||
// 2. 投票类型切换(单选/多选)
|
||||
handleVoteTypeChange(e) {
|
||||
this.setData({
|
||||
"form.vote_type": e.detail,
|
||||
});
|
||||
},
|
||||
|
||||
showPicker(e) {
|
||||
console.log("截止")
|
||||
const { mode } = e?.currentTarget?.dataset;
|
||||
this.setData({
|
||||
mode,
|
||||
[`${mode}Visible`]: true,
|
||||
});
|
||||
console.log("截止2",mo)
|
||||
},
|
||||
hidePicker() {
|
||||
const { mode } = this.data;
|
||||
this.setData({
|
||||
[`${mode}Visible`]: false,
|
||||
});
|
||||
},
|
||||
onConfirm(e) {
|
||||
const { value } = e?.detail;
|
||||
const { mode } = this.data;
|
||||
|
||||
console.log('confirm', value);
|
||||
|
||||
this.setData({
|
||||
[mode]: value,
|
||||
[`${mode}Text`]: value,
|
||||
});
|
||||
|
||||
this.hidePicker();
|
||||
},
|
||||
|
||||
onColumnChange(e) {
|
||||
console.log('pick', e?.detail?.value);
|
||||
},
|
||||
|
||||
|
||||
|
||||
// 6. 投票选项输入
|
||||
handleOptionInput(e) {
|
||||
const { index, key } = e.currentTarget.dataset;
|
||||
this.setData({
|
||||
[`form.options[${index}].${key}`]: e.detail.value,
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
// 8. 删除投票选项(至少保留1个)
|
||||
deleteOption(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
const { options } = this.data.form;
|
||||
if (options.length <= 1) return;
|
||||
|
||||
// 删除后重新排序sort_order
|
||||
const newOptions = options.filter((_, i) => i !== index);
|
||||
newOptions.forEach((item, i) => {
|
||||
item.sort_order = i + 1;
|
||||
});
|
||||
|
||||
this.setData({
|
||||
"form.options": newOptions,
|
||||
});
|
||||
},
|
||||
|
||||
// 9. 表单校验
|
||||
validateForm() {
|
||||
const { title, end_time, options } = this.data.form;
|
||||
|
||||
// 校验标题
|
||||
if (!title.trim()) {
|
||||
wx.showToast({ title: "请输入文章标题", icon: "none" });
|
||||
return false;
|
||||
}
|
||||
|
||||
// 校验结束时间
|
||||
if (!end_time) {
|
||||
wx.showToast({ title: "请选择投票结束时间", icon: "none" });
|
||||
return false;
|
||||
}
|
||||
|
||||
// 校验选项(至少1个,且内容不为空)
|
||||
const hasEmptyOption = options.some(
|
||||
(item) => !item.content.trim()
|
||||
);
|
||||
if (hasEmptyOption) {
|
||||
wx.showToast({ title: "请完善所有选项内容", icon: "none" });
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
// 10. 提交发布
|
||||
handleSubmit() {
|
||||
// 1. 表单校验
|
||||
if (!this.validateForm()) return;
|
||||
|
||||
// 2. 整理提交数据(过滤空值,只保留需求字段)
|
||||
const { title, vote_type, end_time, options } = this.data.form;
|
||||
const submitData = {
|
||||
title: title.trim(),
|
||||
vote_type,
|
||||
end_time,
|
||||
options: options.map((item) => ({
|
||||
content: item.content.trim(),
|
||||
sort_order: item.sort_order,
|
||||
})),
|
||||
};
|
||||
|
||||
// 3. 模拟提交(替换为实际接口请求)
|
||||
this.setData({ isSubmitting: true });
|
||||
console.log("发布投票文章数据:", submitData);
|
||||
|
||||
// 模拟接口请求(2秒后返回成功)
|
||||
setTimeout(() => {
|
||||
wx.showToast({ title: "发布成功" });
|
||||
this.setData({ isSubmitting: false });
|
||||
// 发布成功后返回上一页
|
||||
wx.navigateBack({ delta: 1 });
|
||||
}, 2000);
|
||||
},
|
||||
onChange(e) {
|
||||
this.setData({ value: e.detail.value });
|
||||
},
|
||||
onChange1(e) {
|
||||
this.setData({ value1: e.detail.value });
|
||||
},
|
||||
|
||||
addOption1() {
|
||||
const { form } = this.data;
|
||||
// 最多3个选项
|
||||
if (form.options.length < 5) {
|
||||
// 创建新数组并添加新选项(保持原有选项数据)
|
||||
const newOptions = [...form.options];
|
||||
newOptions.push({
|
||||
content: "",
|
||||
sort_order: newOptions.length + 1
|
||||
});
|
||||
this.setData({
|
||||
'form.options': newOptions
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 删除选项
|
||||
removeOption(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
const { form } = this.data;
|
||||
|
||||
if (form.options.length > 1) {
|
||||
// 过滤掉要删除的选项,保留其他选项数据
|
||||
let newOptions = form.options.filter((_, i) => i !== index);
|
||||
|
||||
// 重新排序(不影响内容,只更新序号)
|
||||
newOptions = newOptions.map((item, i) => ({
|
||||
...item, // 保留原有内容
|
||||
sort_order: i + 1
|
||||
}));
|
||||
|
||||
this.setData({
|
||||
'form.options': newOptions
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 选项内容输入
|
||||
onOptionInput(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
const { form } = this.data;
|
||||
|
||||
|
||||
// 创建新数组避免直接修改原数据
|
||||
const newOptions = [...form.options];
|
||||
// 只更新当前输入的选项内容
|
||||
newOptions[index].content = e.detail.value;
|
||||
console.log("输入:",newOptions[index].content)
|
||||
this.setData({
|
||||
'form.options': newOptions
|
||||
});
|
||||
},
|
||||
onColumnChange(e) {
|
||||
console.log('picker pick:', e);
|
||||
},
|
||||
|
||||
onPickerChange(e) {
|
||||
const { key } = e.currentTarget.dataset;
|
||||
const { value } = e.detail;
|
||||
|
||||
console.log('picker change:', e.detail);
|
||||
this.setData({
|
||||
[`${key}Visible`]: false,
|
||||
[`${key}Value`]: value,
|
||||
[`${key}Text`]: value.join(' '),
|
||||
});
|
||||
},
|
||||
|
||||
onPickerCancel(e) {
|
||||
const { key } = e.currentTarget.dataset;
|
||||
console.log(e, '取消');
|
||||
console.log('picker1 cancel:');
|
||||
this.setData({
|
||||
[`${key}Visible`]: false,
|
||||
});
|
||||
},
|
||||
|
||||
onCityPicker() {
|
||||
this.setData({ cityVisible: true });
|
||||
},
|
||||
|
||||
onSeasonPicker() {
|
||||
this.setData({ dateVisible: true });
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
});
|
||||
149
miniprogram/pages/publish/publish.wxml
Normal file
149
miniprogram/pages/publish/publish.wxml
Normal file
@@ -0,0 +1,149 @@
|
||||
<view class="publish-page">
|
||||
<!-- TDesign 选项卡:普通发布 / 内推码发布 -->
|
||||
<t-tabs
|
||||
defaultValue="{{0}}"
|
||||
theme="card"
|
||||
class="publish-tabs"
|
||||
bind:change="handleTabChange"
|
||||
>
|
||||
<!-- 第一个选项卡:普通发布 -->
|
||||
<t-tab-panel label="普通发布" value="{{0}}" class="tab-panel">
|
||||
<view class="input-example">
|
||||
<view class="input-example__label"> 标签文字 </view>
|
||||
<t-input
|
||||
placeholder="请输入文字"
|
||||
borderless="{{true}}"
|
||||
|
||||
style="{{style}}"
|
||||
/>
|
||||
</view>
|
||||
<view class="wenping-label"> 选择文评类型 </view>
|
||||
<t-radio-group
|
||||
t-class="horizontal-box"
|
||||
value="{{value1}}"
|
||||
bind:change="onChange1"
|
||||
>
|
||||
<view
|
||||
wx:for="{{2}}"
|
||||
wx:key="index"
|
||||
class="card {{value1 == index ? 'card--active' : ''}}"
|
||||
>
|
||||
<!-- 选中时显示对勾图标 -->
|
||||
<t-icon
|
||||
wx:if="{{value1 == index}}"
|
||||
name="check"
|
||||
t-class="card__icon"
|
||||
/>
|
||||
<!-- 单选按钮(隐藏原生图标,用自定义样式替代) -->
|
||||
<t-radio
|
||||
value="{{index}}"
|
||||
label="{{index == 0 ? '单选' : '多选'}}"
|
||||
icon="none"
|
||||
borderless
|
||||
/>
|
||||
</view>
|
||||
</t-radio-group>
|
||||
|
||||
<view class="options-container">
|
||||
<view class="options-header">
|
||||
<view class="options-label">选项设置</view>
|
||||
<t-button theme="primary" size="large" variant="text"
|
||||
bindtap="addOption1" style="margin-left: 40vw;"
|
||||
>添加选项</t-button>
|
||||
</view>
|
||||
|
||||
<!-- 选项列表 - 绑定到form.options -->
|
||||
<view class="options-list">
|
||||
<view wx:for="{{form.options}}" wx:key="index" class="option-item">
|
||||
<t-input
|
||||
placeholder="请输入选项内容"
|
||||
value="{{item.content}}"
|
||||
bind:change="onOptionInput"
|
||||
data-index="{{index}}"
|
||||
class="option-input"
|
||||
/>
|
||||
<t-icon
|
||||
name="delete"
|
||||
size="24rpx"
|
||||
class="delete-option"
|
||||
bind:tap="removeOption"
|
||||
data-index="{{index}}"
|
||||
wx:if="{{form.options.length > 1}}"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="options-hint" wx:if="{{form.options.length > 0}}">
|
||||
已添加 {{form.options.length}}/5 个选项
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<t-cell
|
||||
title="截止时间"
|
||||
hover
|
||||
note="{{datetimeText}}"
|
||||
arrow
|
||||
data-mode="datetime"
|
||||
bindtap="showPicker"
|
||||
t-class="panel-item"
|
||||
/>
|
||||
|
||||
<!-- 年月日时分 -->
|
||||
<t-date-time-picker
|
||||
title="截止时间"
|
||||
visible="{{datetimeVisible}}"
|
||||
mode="second"
|
||||
value="{{datetime}}"
|
||||
format="YYYY-MM-DD HH:mm:ss"
|
||||
bindchange="onConfirm"
|
||||
bindpick="onColumnChange"
|
||||
bindcancel="hidePicker"
|
||||
/>
|
||||
|
||||
|
||||
<view class="button-example">
|
||||
<t-button theme="primary" size="large" block>发布文评</t-button>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
</t-tab-panel>
|
||||
|
||||
<!-- 第二个选项卡:内推码发布 -->
|
||||
<t-tab-panel label="内推码发布" value="{{1}}" class="tab-panel">
|
||||
<t-form class="referral-publish-form" bind:submit="handleReferralSubmit">
|
||||
<!-- 内推码发布表单内容 -->
|
||||
<t-form-item label="公司名称" required>
|
||||
<t-cell class="mb-16" title="选择内推码类型" arrow hover note="{{cityText}}" bind:click="onCityPicker" />
|
||||
<t-picker
|
||||
visible="{{cityVisible}}"
|
||||
value="{{cityValue}}"
|
||||
data-key="city"
|
||||
title="选择内推码类型"
|
||||
cancelBtn="取消"
|
||||
confirmBtn="确认"
|
||||
usingCustomNavbar
|
||||
bindchange="onPickerChange"
|
||||
bindpick="onColumnChange"
|
||||
bindcancel="onPickerCancel"
|
||||
>
|
||||
<t-picker-item options="{{citys}}" format="{{formatter}}">
|
||||
<block wx:for="{{citys}}" wx:key="index" wx:for-item="option">
|
||||
<view wx:if="{{option.tag}}" slot="label-suffix--{{index}}" class="label-suffix">
|
||||
<t-tag size="small" theme="primary">{{option.tag}}</t-tag>
|
||||
</view>
|
||||
</block>
|
||||
</t-picker-item>
|
||||
</t-picker>
|
||||
</t-form-item>
|
||||
|
||||
|
||||
<t-form-item>
|
||||
<t-button type="primary" form-type="submit" class="submit-btn">
|
||||
发布内推码
|
||||
</t-button>
|
||||
</t-form-item>
|
||||
</t-form>
|
||||
</t-tab-panel>
|
||||
</t-tabs>
|
||||
</view>
|
||||
205
miniprogram/pages/publish/publish.wxss
Normal file
205
miniprogram/pages/publish/publish.wxss
Normal file
@@ -0,0 +1,205 @@
|
||||
/* 页面容器 */
|
||||
.publish-page {
|
||||
padding: 24rpx;
|
||||
background-color: #f5f7fa;
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
padding-bottom: 13vh;
|
||||
}
|
||||
|
||||
/* Tabs 选项卡样式 */
|
||||
.publish-tabs {
|
||||
--tabs-card-height: 80rpx; /* 选项卡高度 */
|
||||
--tabs-card-font-size: 28rpx; /* 选项卡文字大小 */
|
||||
--tabs-card-active-color: #ffffff; /* 激活态文字色 */
|
||||
--tabs-card-active-background-color: #1677ff; /* 激活态背景色 */
|
||||
--tabs-card-inactive-color: #333333; /* 未激活文字色 */
|
||||
--tabs-card-inactive-background-color: #ffffff; /* 未激活背景色 */
|
||||
--tabs-card-border-radius: 12rpx; /* 选项卡圆角 */
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
/* 选项卡面板样式 */
|
||||
.tab-panel {
|
||||
background-color: #ffffff;
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx 24rpx;
|
||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
/* 普通发布表单样式 */
|
||||
.common-publish-form,
|
||||
.referral-publish-form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* 表单项间距 */
|
||||
.t-form-item {
|
||||
margin-bottom: 30rpx !important;
|
||||
}
|
||||
|
||||
/* 表单标签样式 */
|
||||
.t-form-item__label {
|
||||
font-size: 28rpx !important;
|
||||
color: #333333 !important;
|
||||
width: 160rpx !important; /* 固定标签宽度,对齐更整齐 */
|
||||
}
|
||||
|
||||
/* 输入框样式 */
|
||||
.t-input,
|
||||
.t-textarea {
|
||||
--input-height: 72rpx !important;
|
||||
--input-font-size: 26rpx !important;
|
||||
--input-placeholder-color: #999999 !important;
|
||||
--input-border-radius: 10rpx !important;
|
||||
}
|
||||
|
||||
/* 提交按钮样式 */
|
||||
.submit-btn {
|
||||
--button-height: 88rpx !important;
|
||||
--button-font-size: 30rpx !important;
|
||||
--button-primary-background-color: #1677ff !important;
|
||||
--button-border-radius: 12rpx !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input-example {
|
||||
--td-input-vertical-padding: 24rpx;
|
||||
background-color: var(--bg-color-demo);
|
||||
padding: 32rpx 32rpx 16rpx;
|
||||
}
|
||||
|
||||
.input-example__label {
|
||||
color: var(--td-text-color-primary);
|
||||
font-size: 24rpx;
|
||||
line-height: 40rpx;
|
||||
margin: 0 8rpx 16rpx;
|
||||
}
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
border: 3rpx solid var(--td-bg-color-container, #fff);
|
||||
background-color: #c09d9d !important;
|
||||
}
|
||||
.card--active {
|
||||
border-color: var(--td-brand-color, #0052d9);
|
||||
}
|
||||
|
||||
.card--active::after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 0;
|
||||
border-width: 28px 28px 28px 0;
|
||||
border-style: solid;
|
||||
border-color: var(--td-brand-color, #0052d9) transparent transparent transparent;
|
||||
}
|
||||
|
||||
.card__icon {
|
||||
color: var(--td-bg-color-container, #fff);
|
||||
position: absolute;
|
||||
left: 1.5px;
|
||||
top: 1.5px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 横向布局 */
|
||||
.horizontal-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
margin: 32rpx;
|
||||
}
|
||||
|
||||
.horizontal-box .card {
|
||||
flex: 0 0 calc(50.33% - 12rpx);
|
||||
margin: 0 0 24rpx 0;
|
||||
}
|
||||
.wenping-label{
|
||||
margin-left: 5vw;
|
||||
}
|
||||
.wenping-label{
|
||||
font-size: 24rpx;
|
||||
}
|
||||
/* 选项容器样式 */
|
||||
.options-container {
|
||||
margin-top: 40rpx;
|
||||
padding: 24rpx;
|
||||
background-color: #f9f9f9;
|
||||
border-radius: 12rpx;
|
||||
}
|
||||
|
||||
/* 选项头部 */
|
||||
.options-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.options-label {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.add-option-btn {
|
||||
height: 56rpx;
|
||||
line-height: 56rpx;
|
||||
padding: 0 20rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
/* 选项列表 */
|
||||
.options-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.option-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
background-color: #fff;
|
||||
padding: 12rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
.option-input {
|
||||
flex: 1;
|
||||
--input-height: 60rpx !important;
|
||||
--input-font-size: 26rpx !important;
|
||||
}
|
||||
|
||||
.delete-option {
|
||||
color: #ff4d4f;
|
||||
padding: 8rpx;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* 选项提示 */
|
||||
.options-hint {
|
||||
margin-top: 16rpx;
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.submit-container{
|
||||
width: 100%;
|
||||
height: 20vh;
|
||||
background: red;
|
||||
|
||||
}
|
||||
.button-example {
|
||||
margin: 32rpx;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user